我有多个子目录,我想使用 Mac 上的一行终端命令将其中包含的所有文件移动到当前目录。我知道我的文件名并不都是唯一的,我想在文件扩展名前添加后缀。
我发现了类似的问题问:将子目录中的所有文件移动到当前目录?建议使用:
find ./*/* -type f -print0 | xargs -0 -J % mv % .
但这只对唯一的文件名有用。例如,给定以下树:
.
├── bar
│ ├── test1.jpg
│ ├── test2.jpg
│ └── test3.jpg
├── foo
│ ├── test1.jpg
│ ├── test2.jpg
│ └── test3.jpg
├── qux
│ └── test3.jpg
└── corge
└── test3.jpg
我希望看到类似的结果:
.
├── bar
├── foo
├── qux
├── corge
├── test1.jpg
├── test1a.jpg
├── test2.jpg
├── test2a.jpg
├── test3.jpg
├── test3a.jpg
├── test3b.jpg
└── test3c.jpg
有人可以帮忙吗?
答案1
获取当前目录中每个文件的所有常规文件的递归列表,剪切其中的前导“。”和斜线,将目录和文件名连接成一个唯一的字符串,然后将其移动到当前目录
list=$(find . -type f)
for file in $list; do
echo -n "$file to "
echo $file|cut -d '.' -f2-99| tr -d '/'
mv "$file" ./"$(echo $file|cut -d '.' -f2| tr -d '/')"
done
答案2
将此脚本复制到您的顶级目录,使其可执行并运行它:
#!/bin/bash
## Get a list of all files
list=$(find . -mindepth 2 -type f -print)
nr=1
## Move all files that are unique
find . -mindepth 2 -type f -print0 | while IFS= read -r -d '' file; do
mv -n "$file" ./
done
list=$(find . -mindepth 2 -type f -print)
## Checking which files need to be renamed
while [[ $list != '' ]] ; do
##Remaming the un-moved files to unique names and move the renamed files
find . -mindepth 2 -type f -print0 | while IFS= read -r -d '' file; do
current_file=$(basename "$file")
mv -n "$file" "./${nr}${current_file}"
done
## Incrementing counter to prefix to file name
nr=$((nr+1))
list=$(find . -mindepth 2 -type f -print)
done
答案3
除非您的示例中的严格顺序命名对您来说非常重要,否则我建议采用以下“保持简单”/“快速而肮脏”的解决方案:
find . -type f |
while read filename; do
basename=$(basename "$filename");
newname=$(echo "$basename" | sed "s/^\(.*\)\(\.[^\.]\+\)$/\1(XXXX)\2/");
printf "mv \"%s\" \"%s\";\n" "$filename" "$(mktemp -u "$newname")";
done
这只会打印将要执行的命令,因此请通过检查输出来检查其合理性,然后复制并粘贴到命令行中,如果一切都令您满意。
用英文来说:找到所有常规文件,将它们的文件名从“test1.jpg”转换为“test1(XXXX).jpg”形式,其中“XXXX”将被挑选出来并由 mktemp 用随机字符替换,然后为此操作创建“mv”命令行。
为了进一步降低文件名冲突风险,只需添加更多“X”即可。
玩得开心。