![递归复制文件并重命名](https://linux22.com/image/68217/%E9%80%92%E5%BD%92%E5%A4%8D%E5%88%B6%E6%96%87%E4%BB%B6%E5%B9%B6%E9%87%8D%E5%91%BD%E5%90%8D.png)
如果我的输入文件夹files_input
包含01-2015
、等子文件夹02-2015
,03-2015
并且所有这些子文件夹都有其他子文件夹。每个子文件夹只有一个名为index.html
.
如何将所有这些index.html
文件复制到一个名为 的文件夹中files_output
,以便它们最终像同一文件夹中的单独文件一样。它们当然应该被重命名,我已经尝试使用 --backup 来做到这一点......
我努力了
find files_input -name \*.html -exec cp --backup=t '{}' files_output \;
给它们编号,但只复制一个文件,没有其他任何内容。
我不知道这会改变什么,但我正在使用 zsh,以下是版本:
$ zsh --version | head -1
zsh 5.0.2 (x86_64-pc-linux-gnu)
$ bash --version | head -1
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
$ cp --version | head -1
cp (GNU coreutils) 8.21
$ find --version | head -1
find (GNU findutils) 4.4.2
有想法吗?
编辑:
尝试运行例如以下
cp --backup=t files_input/01-2015/index.html files_output
连续五次仍然在files_output
文件夹中给我一个index.html! cp断了吗?为什么我没有五个不同的文件?
答案1
当您是zsh
用户时:
$ tree files_input
files_input
|-- 01_2015
| |-- subfolder-1
| | `-- index.html
| |-- subfolder-2
| | `-- index.html
| |-- subfolder-3
| | `-- index.html
| |-- subfolder-4
| | `-- index.html
| `-- subfolder-5
| `-- index.html
|-- 02_2015
| |-- subfolder-1
| | `-- index.html
| |-- subfolder-2
| | `-- index.html
| |-- subfolder-3
| | `-- index.html
| |-- subfolder-4
| | `-- index.html
| `-- subfolder-5
| `-- index.html
(etc.)
$ mkdir -p files_output
$ autoload -U zmv
$ zmv -C './files_input/(*)/(*)/index.html' './files_output/$1-$2-index.html'
$ tree files_output
files_output
|-- 01_2015-subfolder-1-index.html
|-- 01_2015-subfolder-2-index.html
|-- 01_2015-subfolder-3-index.html
|-- 01_2015-subfolder-4-index.html
|-- 01_2015-subfolder-5-index.html
|-- 02_2015-subfolder-1-index.html
|-- 02_2015-subfolder-2-index.html
(etc.)
这里发生的事情是我们使命令zmv
可用autoload -U zmv
。该命令用于重命名、复制或链接匹配的文件zsh
扩展的通配模式。
我们使用zmv
它的-C
选项,告诉它复制文件(而不是移动它们,这是默认的)。然后,我们指定一个与我们想要复制的文件相匹配的模式,./files_input/(*)/(*)/index.html
.两者(*)
匹配两级子目录名称,我们将它们放在括号内,以便在每个文件的新名称中使用。每个文件的新名称是第二个参数 ,./files_output/$1-$2-index.html
其中$1
和$2
是模式中括号捕获的字符串,即对子目录名称的反向引用。两个参数都应该用单引号引起来。
答案2
你可以这样做:
cd -P files_input/.. &&
mkdir files_output &&
pax -rws'|.*/\(.*\)/\(.*\)|\1.\2|' \
files_input/??-2015/index.html files_output
这将全局所有index.html
子目录中的文件夹中的文件./files_input
用两个字符命名,然后是破折号,然后是字符串2015
并将所有这些文件复制到新创建的files_output
名称类似的文件夹??-2015.index.html
。
答案3
尝试删除周围的引号{}
,因为这似乎对我有用。
$ find foo* files_output -ls
27002 0 drwxrwxr-x 2 steve steve 60 Jul 2 15:04 foo1
25373 0 -rw-rw-r-- 1 steve steve 0 Jul 2 15:04 foo1/index.html
27003 0 drwxrwxr-x 2 steve steve 60 Jul 2 15:04 foo2
25374 0 -rw-rw-r-- 1 steve steve 0 Jul 2 15:04 foo2/index.html
48941 0 drwxrwxr-x 2 steve steve 40 Jul 2 15:06 files_output
$ find foo* -name index.html -exec cp --backup=t {} files_output \;
$ find files_output -ls
48941 0 drwxrwxr-x 2 steve steve 80 Jul 2 15:08 files_output
51354 0 -rw-rw-r-- 1 steve steve 0 Jul 2 15:08 files_output/index.html
49595 0 -rw-rw-r-- 1 steve steve 0 Jul 2 15:08 files_output/index.html.~1~
$
就我而言,实用程序的版本如下。
$ bash --version | head -1
GNU bash, version 4.2.53(1)-release (x86_64-redhat-linux-gnu)
$ cp --version | head -1
cp (GNU coreutils) 8.21
$ find --version | head -1
find (GNU findutils) 4.5.11
$
答案4
这对我有用:
find files_input -name "\20171123*" -exec cp --backup=t --target-directory=files_output {} +
将与“files_input”的目录和子目录中的模式匹配的所有文件复制-name
到“file_output”目录,并为重复文件附加 ~1~、~2~ 等。