我有一个文件系统树,其中的不同位置都有同名的文件。我在命令行尝试了以下命令:
find / -name "HAHA" -exec mv {} /home \;
它仅适用于一个文件,对于其他文件,我收到一条具有相同名称的错误消息。
我可以更改命令,为每个文件名附加一个数字来区分它们吗?
答案1
我可以想到两种可能的解决方案:
如果您是
mv
从GNU 核心工具(可能是这种情况),然后执行以下命令...find / -name "HAHA" -type f -exec mv --backup=numbered "{}" /home \;
...将把所有调用的文件移动
HAHA
到/home
.这--backup=numbered
选项ofmv
确保每次mv
执行该命令时,它都会检查目标目录中是否已存在指定的文件HAHA
- 如果存在,则首先将其重命名为HAHA.~n~
(其中n
是递增的数字),然后再将新文件移动到/home
。最后,您将得到名为HAHA
、HAHA.~1~
等HAHA.~2~
的文件/home
。这个 shell 脚本应该可以解决问题,但它不能抵抗包含换行符的路径:
IFS=" " # if you are using bash, you can just use IFS=$'\n' here i=1 for file in $(find / -name "HAHA" -type f); do mv "${file}" "/home/HAHA${i}" i=$((${i} + 1)) done
这会迭代所有
HAHA
文件并将每个文件移动到/home/HAHAn
,其中的n
数字又从 1 开始递增。
答案2
我找到了一个带有小脚本的简单解决方案。该脚本被称为cpf
(或您给它起的任何名称),如下所示:
#!/bin/bash
dir=xyz # Directory where you want the files
num=1
for file in "$@"
do
base=`basename -- "$file"`
mv -- "$file" "$dir/$base.$num"
num=$(($num+1))
done
您执行命令如下:
find . -name HAHA -print0 | xargs -0x cpf
答案3
我会使用while
循环:
i=1
find / -name 'HAHA' -print0 | while read -d '' -r file; do mv "$file" "/home/${file##.*/}$((i++))"; done
这里重要的是其中print0
的选项find
(与-d ''
选项一起read
)正确处理名称中带有空格的文件。如果您只需要执行一次此类操作,则i=1
不需要设置第一行,因为bash
(以及大多数其他 shell)将简单地自动创建此变量。
答案4
可以使用 GNU 并行
find / -name "HAHA" -type f | parallel 'echo mv {}
./dest-dir/{/}_`stat -c%i {}`
{/} ............. returns dirname
{/.} ............. dirname with no extension
stat -c%i {} ..... gets the inode for each file "whic is unique"
OBS:我是echo
为了测试而使用的,如果满足你的需求就删除它