1

我不想复制包含文件和文件夹的特定文件夹结构,并有一个输出告诉用户复制的距离。

目前我使用以下内容来复制没有某些特定文件夹的结构:

cp -rfv !(Project.buildoutput) $Project_SYNC_DIR

但是cp -v输出非常难看:

> _55_studio.tests/singles/CustomIdentifier.file -> /Users/<path>/_55_studio.tests/singles/CustomIdentifier.file build.sh
> -> /Users/<path>/build.sh

是否可以仅输出具有干净名称的级别 1 元素。

我当前的文件夹结构:

_55_studio
--singles
--mixed
_55_studio.tests
--singles
build.sh
project.settings

复制时输出到以下内容:

Copy folder _55_studio
Copy folder _55_studio.tests
Copy file build.sh
Copy file project.settings

有没有一种有效的方法来实现这一目标以及如何实现?

BR,迈贝克

4

3 回答 3

1

在单行中使用find

find "/path/to/dir" -maxdepth 1 -mindepth 1 -name "Project.buildoutput" -prune -o -exec /bin/bash -c "echo -en \"Copy \"; \
                                                                                                      [ -d '{}' ] && echo -en \"folder \";\
                                                                                                      [ -f '{}' ] && echo -en \"file \"; \
                                                                                                      basename '{}'; \
                                                                                                      cp -fr '{}' \"$Project_SYNC_DIR\"" \;

输出:

Copy folder _55_studio
Copy folder _55_studio.tests
Copy file build.sh
Copy file project.settings
于 2013-01-11T10:41:10.750 回答
1

第一步,提取目录:

sed -e 's#^\([^/]\+\) -> .*$#\1#g' -e 's#^\([^/]\+\)/.*$#\1#g'

第一个替换,替换像这样的行:

`file_name' -> `path/to/copy/file_name'

到:

file_name

第二个替换,替换像这样的行:

`path/to/file' -> `other/path/to/copy/file'

到:

path

请注意,我添加了 ` 和 ' 因为我的 cp 添加了它们。

第 2 步,删除重复项:

uniq

第三步,查看是文件还是目录:

while read f; do \
  if [ -d $f ]; then \
    echo Copy folder $f \
  else \
     echo Copy file $f \
  fi \
done

所以:

cp -rfv !(Project.buildoutput) $Project_SYNC_DIR | \
  sed -e 's#^`\([^/]\+\)'"'"' -> .*$#\1#g' \
      -e 's#^`\([^/]\+\)/.*$#\1#g' | \
  uniq | \
  while read f; do \
    if [ -d $f ]; then \
      echo Copy folder $f; \
    else \
      echo Copy file $f; \
    fi \
  done
于 2013-01-11T10:50:07.957 回答
1

一种非常接近您所要求的有效方法:

for src in !(Project.buildoutput); do 
    stat -c "Copy %-14F %n" "${src}"; cp -rf "$src" $Project_SYNC_DIR; done

(需要shopt -s extglob扩展通配符: ! 反转匹配)

或显示每个文件/目录

unbuffer cp -rfv !(Project.buildoutput) $Project_SYNC_DIR | 
    while read src dd dst; do stat -c "Copy %-14F %n" "$src"; done 

上面使用的GNU stat,代替 *BSD 使用stat -f "Copy %-14SHT %N"

我的(GNU coreutils 6.9)cp -v坚持在输出中打印断引号,使用上述方法的快速破解是tr在管道中添加一个:

...  | tr -d \`\' | while ...

如果您的文件/目录名称中有空格或单引号,则需要更详细的内容。

如果你喜欢 perl 做你的繁重工作(并处理 `' 引用);

... | perl -ne $'/\`(.*)\' -> \`(.*)\'/ && 
  printf("Copy %-14s %s\n",(-f $1 ? "file" : -d $1 ? "directory" : "<other>"),$1);'

如果您有很多文件,这应该会更有效,因为只需要一个额外的进程,而不是每个文件/目录复制一个。

在复制期间获得更多反馈的常见解决方案是使用rsync

rsync --progress -hrv src/ dest/ 

rsync比 更有效cp,它不会复制不需要的文件,添加“ -W”以强制复制cp.

于 2013-01-11T11:17:00.880 回答