输出要复制的当前文件夹/文件的文件夹/文件名

时间:2013-01-11 10:21:01

标签: bash copy

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

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

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, mybecks

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

第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

步骤3,检查它是否是文件或目录:

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

答案 2 :(得分:1)

一种非常接近你问的方式的有效方法:

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

(需要shopt -s extglob用于扩展的globbing:!来反转匹配)

或显示每个文件/目录

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/ 

rsynccp效率更高,它不会复制不需要的文件,添加“-W”来强制像cp这样的副本。