如何将目录展平为以下格式?
前:./aaa/bbb/ccc.png
后:./aaa-bbb-ccc.png
答案1
虽然这里已经有很好的答案,但我发现这更直观,在bash
:
find aaa -type f -exec sh -c 'new=$(echo "{}" | tr "/" "-" | tr " " "_"); mv "{}" "$new"' \;
aaa
您现有的目录在哪里。它包含的文件将被移动到当前目录(只留下aaa中的空目录)。这两个调用tr
处理目录和空间(没有转义斜杠的逻辑 - 供读者练习)。
我认为这更直观并且相对容易调整。find
即,如果我只想查找 .png 文件,我可以更改参数。我可以更改tr
呼叫,或根据需要添加更多呼叫。如果我想目视检查它是否会做正确的事情,我可以echo
在之前添加(然后仅当事情看起来正确时才重复而不需要额外的操作:mv
echo
find aaa -name \*.png -exec sh -c 'new=$(echo "{}" | tr "/" "-" | tr " " "_"); echo mv "{}" "$new"' \;
另请注意,我使用的是find aaa
... 而不是find .
... 或find aaa/
...,因为后两者会在最终文件名中留下有趣的痕迹。
答案2
警告:我直接在浏览器中输入了大部分命令。警告讲师。
使用 zsh 和兹马夫:
zmv -o -i -Qn '(**/)(*)(D)' '${1//\//-}$2'
说明:该模式**/*
递归地匹配当前目录的子目录中的所有文件(它不匹配当前目录中的文件,但这些文件不需要重命名)。前两对括号是可以在替换文本中引用为$1
和的组。$2
最后一对括号添加D
全局限定符这样点文件就不会被遗漏。-o -i
意味着传递该-i
选项,mv
以便提示您是否覆盖现有文件。
仅使用 POSIX 工具:
find . -depth -exec sh -c '
for source; do
case $source in ./*/*)
target="$(printf %sz "${source#./}" | tr / -)";
mv -i -- "$source" "${target%z}";;
esac
done
' _ {} +
说明:该case
语句省略了当前目录和当前目录的顶级子目录。target
包含源文件名 ( $0
),前导./
已被去除,所有斜杠均替换为破折号,最后加上z
.最后一个z
是为了防止文件名以换行符结尾:否则命令替换将删除它。
如果你find
不支持-exec … +
(OpenBSD,我正在看着你):
find . -depth -exec sh -c '
case $0 in ./*/*)
target="$(printf %sz "${0#./}" | tr / -)";
mv -i -- "$0" "${target%z}";;
esac
' {} \;
使用 bash(或 ksh93),您不需要调用外部命令来用破折号替换斜杠,您可以使用带有字符串替换构造的 ksh93 参数扩展${VAR//STRING/REPLACEMENT}
:
find . -depth -exec bash -c '
for source; do
case $source in ./*/*)
source=${source#./}
target="${source//\//-}";
mv -i -- "$source" "$target";;
esac
done
' _ {} +
答案3
find . -mindepth 2 -type f -name '*' |
perl -l000ne 'print $_; s/\//-/g; s/^\.-/.\// and print' |
xargs -0n2 mv
注意:这不适用于包含\n
.
当然,这只会移动类型f
文件...
唯一的名称冲突来自于预先存在于密码
使用这个基本子集进行测试
rm -fr junk
rm -f junk*hello*
mkdir -p junk/junkier/junkiest
touch 'hello hello'
touch 'junk/hello hello'
touch 'junk/junkier/hello hello'
touch 'junk/junkier/junkiest/hello hello'
导致
./hello hello
./junk-hello hello
./junk-junkier-hello hello
./junk-junkier-junkiest-hello hello
答案4
只需通过管道将文件名+路径传递给tr
命令即可。tr <replace> <with>
for FILE in `find aaa -name "*.png"`
do
NEWFILE=`echo $FILE | tr '/' '-'`
cp -v $FILE $NEWFILE
done