我有一个文件夹,里面有许多文件 ABC.* (大约有 100 个这样的文件)。我想将它们全部复制到名称以 DEF 开头的新文件中。*
所以,我想要
ABC.Page1
ABC.Page2
ABC.Topic12
...etc
复制到
DEF.Page1
DEF.Page2
DEF.Topic12
...etc
使用批处理命令(在 BASH 或类似命令中)执行此操作的最简单方法是什么?我正在考虑涉及 sed 或 awk 或 xargs 的问题,但我很难弄清楚语法。我可以编写一个 Python 脚本,但我认为可能有一个不太复杂的命令行解决方案。
答案1
在 bash 中这样的事情怎么样:
for file in ABC.*; do cp "$file" "${file/ABC/DEF}";done
您可以通过将 echo 放在 cp 命令前面来测试它:
for file in ABC.*; do echo cp "$file" "${file/ABC/DEF}";done
答案2
为了有效地处理大量文件,最好避免cp
为每个文件启动不同的进程。一种方法是复制然后使用重命名它们prename
(rename
在基于 Debian 的发行版上默认符号链接到此)。使用这个和Linux mktemp
:
tmp=$(mktemp -d --tmpdir=.)
cp ABC.* "$tmp"
prename "s:$tmp/ABC:DEF:" "$tmp/"*
rmdir "$tmp"
更新
实际上pax
可能是更好的方法:
pax -rws '/^ABC/DEF/' ABC.* .
不幸的是,尽管它pax
同时是 POSIX 和 Linux 标准库,但目前很少有发行版默认包含它。
答案3
tar
会非常快地为您做这件事。
测试
首先我创建了 2 个目录和 10 个文件:
% mkdir test1 test2 ; cd test1
% for n in `seq 1 10` ; do touch ABC.file$n ; done
% ls
> ABC.file1 ABC.file2 ABC.file4 ABC.file6 ABC.file8
> ABC.file10 ABC.file3 ABC.file5 ABC.file7 ABC.file9
然后我复制了它们:
% tar -cf - ./* |\
tar -C../test2 --transform='s/ABC/DEF/' -xf -
% ls ../test2
> DEF.file1 DEF.file2 DEF.file4 DEF.file6 DEF.file8
> DEF.file10 DEF.file3 DEF.file5 DEF.file7 DEF.file9
转换
因此 GNUtar
将接受sed --transform=EXPRESSION
文件重命名。这甚至可以仅重命名某些文件。例如:
% tar -cf - ./* |\
tar -C../test2 --transform='s/ABC\(.*[0-5]\)/DEF\1/' -xf -
% ls ../test2
> ABC.file6 ABC.file8 DEF.file1 DEF.file2 DEF.file4
> ABC.file7 ABC.file9 DEF.file10 DEF.file3 DEF.file5
这是一个优势。
溪流
还要考虑到这只是两个tar
进程 - 并且无论您的文件数量如何,都不会改变。
tar | tar
tar
正如您所希望的那样进行优化。这永远不会出现参数计数问题或失控的子进程。这只是甲>乙完毕。
论点
我在这里使用两个tar
进程之间组合的 7 个不同的参数。最重要的首先列出在这里:
-
标准输出/标准输入- 这表明tar
它将流式传输其输入或输出stdin/stdout
它将根据是否正在构建或提取档案来正确解释。
-c
创造- 这告诉tar
我们建立档案。下一个参数tar
预期是......
-f
文件- 我们指定tar
将使用file
对象而不是磁带设备或其他设备。如上所述,它将使用的文件是stdin/stdout
- 换句话说,我们的|pipe
。
./*
所有 $PWD/文件- 这里没有太多解释,除了存档参数是第一位的,所以-
然后./*
。
|pipe
...而在...的另一边
-C
改变目录- 这表明tar
它需要在执行任何其他操作之前更改为我指定的目录,因此在cd ../test2
提取之前有效。
--transform='s/ed/EXPR/'
- 正如已经提到的,这完成了重命名。但文档表明它可以采用任何sed
表达式 或//flag
.
-x
提炼-tar
更改目标目录并收到重命名指令后,我们指示它开始从存档文件中将所有文件提取到当前目录中-f - |pipe
。没有什么神秘的。
答案4
在 zsh 中,将以下行放入您的.zshrc
:
autoload -U zmv
alias zmv='noglob zmv'
alias zcp='zmv -C'
alias zln='zmv -L'
然后,在命令行上,你可以跑
zcp 'ABC(.*)' 'DEF$1'
或者简单地
zcp -W ABC.* DEF.*
在另一个 shell 中,只要安装了 zsh:
zsh -c 'autoload zmv; noglob zmv -CW ABC.* DEF.*'