Find 是一个很棒的实用程序 - 而且用途广泛。我尝试通过向现有文件名添加后缀或前缀来重命名文件。凉爽的。
find -name "*" -exec mv {} {}.yo \;
现在这是我无法理解的部分 -如果必须撤消上述操作,我该怎么办?
编辑 -
我注意到前缀是不可能的 - 有解决这个问题的方法吗?
find -type f -name "*" -exec mv {} yu.{} \;
mv: cannot move './o.txt.yu.yu' to 'yu../o.txt.yu.yu': No such file or directory
答案1
find . -depth -name '*.yo' -exec sh -c '
ret=0
for file do
mv -i -- "$file" "${file%.yo}" || ret=$?
done
exit "$ret"' sh {} +
这会将所有file.yo
文件(任何类型,包括目录,如您用于添加该.yo
后缀的命令中的目录)重命名为file
without .yo
.我们正在以深度优先的方式进行操作(在它们所在的分支之前离开),否则如果您重命名dir.yo
为dir
第一个,那么当我们重命名dir.yo/file.yo
为该名称时dir.yo/file
,它将无法工作,因为它dir.yo
不再存在。
使用批量重命名时,-depth
几乎总是更好,因此始终使用它是一个好习惯,唯一要记住的是它与-prune
.
前缀 withmv {} prefix{}
不起作用,因为{}
包含包含目录组件的完整路径,而您想要将前缀添加到文件名中,因此您需要类似以下内容:
find . -depth -type f -exec sh -c '
ret=0
for file do
dir=${file%/*} name=${file##*/}
mv -i -- "$file" "$dir/yu.$name" || ret=$?
done
exit "$ret"' sh {} +
这次我们-type f
只用来重命名常规的文件,排除所有其他类型的文件,包括目录,先进先出,设备,符号链接, ETC。
mmv
我建议使用专用的批量重命名工具,例如orzsh
的,而不是手动执行此类操作zmv
。
在zsh
:
autoload -Uz zmv
zmv '(**/)(*).yo(#qD)' '$1$2' # remove .yo suffix
zmv '(**/)(*)(#qD.)' '${1}yu.$2' # add yu. prefix to regular files
(#q...)
是为了全局限定符whereD
告诉 zmv 也像find
默认情况下一样考虑隐藏文件或隐藏目录中的文件,并且.
相当于find
s -type f
。
答案2
扭转:
find -name "*" -exec mv {} {}.yo \;
一个简单的方法可能是:
首先创建一个脚本“unyo.bash”
#!/usr/bin/env bash
for name in "$@"; do
mv "$name" "${name%.yo}"
done
然后用它来取消你的文件:
find -name "*.yo" -print0 | xargs -0 /path/to/unyo.bash
如果你没有“print0”和“xargs -0”,你可能需要一一执行它们(效率低下,因为它每次都会产生一个bash):
find -name "*.yo" -exec /path/to/unyo.bash '{}' \;
答案3
yu../
没有这样的文件或目录。
尝试这个
find * -type f -exec echo {} pref_{} \;
*
星号 展开到当前目录中的所有文件,不包含 dir,
如果有子目录使用该选项-prune
,则不深入到它
还有这样的构造
find -type f -exec bash -c 'echo $0 ${0%%/*}/pref_${0##*/}' {} \;
但在其中,位置变量从 $0 开始倒计时,即位于{$0 $1 $2 ...} +
或的所有文件{$0} \;
因此,文件数量可以如下计算
find -type f -exec bash -c 'echo $#' 1 {} +
你可以像这样显示所有文件
find -type f -exec bash -c 'echo $@' 1 {} +
在这里,您可以使用任何不带空格的字符或单词,而不是一个。这将意味着 $0 变量中的另一个附加文件
答案4
现在这是我无法理解的部分 - 如果必须撤消上述操作,我该怎么做?
您可以使用以下命令。
for FILENAME in `find . -name "*.yo"`; do mv "$FILENAME" $(echo "$FILENAME" | sed -e 's/\.[^.]*$//'); done