在bash中使用正则表达式查找并复制(保留文件夹结构)?

3
我有一个文件夹,里面有很多日志文件。每组日志文件都在一个详细记录程序运行时间和日期的文件夹中。在这些日志文件夹中,我有一些视频文件需要提取。我只想要视频文件,不需要其他东西。我尝试使用以下命令来复制视频文件,但由于目录不存在,它并没有起作用。
.rmv是我想要的文件扩展名。
$ find . -regex ".*\.rmv" -type f -exec cp '{}' /copy/to/here/'{}'

如果我有这样的文件夹结构:
|--root  
   |  
   |--folder1  
   |  |  
   |  |--file.rmv  
   |  
   |--folder2  
      |  
      |--file2.rmv  

我该如何将它复制到copy/to/here,同时在目标目录中复制folder1和folder2的结构?

4个回答

12

cp有一个--parents参数,因此实现你要做的最短方式是:

find root -name '*.rmv' -type f -exec cp --parents "{}" /copy/to/here \;

2

如果我使用rsync,然后在复制到的目录上运行rmdir(因为它会创建没有任何内容的文件夹),那么这将起作用。我使用了以下命令:'rsync -rv root copy/to/here --exclude=".log" --include=".rmv"'目录中唯一的其他文件是.log文件。出于某种原因,如果我只指定包含,则仍将复制所有文件。谢谢。 - Jonathan Sternberg
@Jonathan:看看 --prune-empty-dirs--delete* 选项是否有用。 - Dennis Williamson

1

{} 表示找到文件的完整路径,因此您的 cp 命令将评估为以下内容:

cp /root/folder1/file.rmv /copy/to/here/root/folder1/file.rmv

如果您只是刪除第二個 {},它將會成為:
cp /root/folder1/file.rmv /copy/to/here

可以使用 cp 命令中的 copy-file-to-directory 形式来实现。

此外,你还可以使用 -name 操作数代替 -regex

find root -name '*.rmv' -type f -exec cp {} /copy/to/here \;

这个方法不可行,因为它无法保留文件夹结构。在文件夹内,有些文件的名称相同。因此,我无法获取所有文件,因为一些文件会被覆盖。 - Jonathan Sternberg

0
假设src是您的root,而dst是您的/copy/to/here
#!/bin/sh

find . -name *.rmv | while read f
do
       path=$(dirname "$f" | sed -re 's/src(\/)?/dst\1/')
       echo "$f -> $path"
       mkdir -p "$path"
       cp "$f" "$path"
done

将此代码放在cp.sh文件中,并在 root 目录下运行./cp.sh 输出:
./src/folder1/file.rmv -> ./dst/folder1
./src/My File.rmv -> ./dst
./src/folder2/file2.rmv -> ./dst/folder2

编辑:改进的脚本版本(感谢评论)


如果名称中有空格,这将无法工作。请改用 find ... | while read f ...。此外,出于同样的原因,您应该引用文件名变量:"$f""$path"。使用 echo "$f -> $path" - 这更易读。如果您的 shell 支持它(大多数都支持),请使用 $() 代替 反引号。顺便说一下,这些分号都不是必需的。 - Dennis Williamson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接