Unix shell文件复制flattening文件夹结构

Ser*_*sta 39 unix shell

在UNIX bash shell(特别是Mac OS X Leopard)上,将具有特定扩展名的每个文件从文件夹层次结构(包括子目录)复制到同一目标文件夹(没有子文件夹)的最简单方法是什么?

显然存在源层次结构中存在重复的问题.我不介意他们被覆盖.

示例:我需要复制以下层次结构中的每个.txt文件

/foo/a.txt
/foo/x.jpg
/foo/bar/a.txt
/foo/bar/c.jpg
/foo/bar/b.txt
Run Code Online (Sandbox Code Playgroud)

到名为'dest'的文件夹并获取:

/dest/a.txt
/dest/b.txt
Run Code Online (Sandbox Code Playgroud)

Mag*_*off 53

在bash中:

find /foo -iname '*.txt' -exec cp \{\} /dest/ \;
Run Code Online (Sandbox Code Playgroud)

find将找到/foo匹配通配符的路径下的所有文件*.txt,不区分大小写(这就是-iname意味着什么).对于每个文件,find将执行cp {} /dest/,找到的文件代替{}.

  • -exec cp -t dest/{} +会更快,因为它只需要运行cp一次,带有多个参数.-t是--target-directory的缩写.-l在这里可能很有用,可以制作硬链接.代替.也许-u,最终得到每个文件名的最新版本,而不是第一个找到的. (3认同)

Ste*_*ton 13

Magnus解决方案的唯一问题是它为每个文件分配了一个新的"cp"进程,这不是特别有效,特别是如果有大量文件的话.

在Linux(或其他具有GNU coreutils的系统)上,您可以:

find . -name "*.xml" -print0 | xargs -0 echo cp -t a
Run Code Online (Sandbox Code Playgroud)

(-0允许它在文件名中包含奇怪的字符(如空格)时工作.)

不幸的是,我认为Macs配备了BSD风格的工具.有人知道"标准"等同于"-t"开关吗?


Rob*_*les 11

The answers above don't allow for name collisions as the asker didn't mind files being over-written.

I do mind files being over-written so came up with a different approach. Replacing each/in the path with - keep the hierarchy in the names, and puts all the files in one flat folder.

We use find to get the list of all files, then awk to create a mv command with the original filename and the modified filename then pass those to bash to be executed.

find ./from -type f | awk '{ str=$0; sub(/\.\//, "", str); gsub(/\//, "-", str); print "mv " $0 " ./to/" str }' | bash
Run Code Online (Sandbox Code Playgroud)

where ./from and ./to are directories to mv from and to.

  • 这不会考虑文件名中的奇数字符,例如空格. (3认同)
  • @ NathanJ.Brauer你可以通过在最后的mv命令中明智地放置\来解决这个问题.(我尝试编辑答案以显示这个但被拒绝.感谢版主.) (3认同)