Linux,使用bash“no such file or directory”错误重命名文件

zengzsys  于 2023-02-21  发布在  Linux
关注(0)|答案(5)|浏览(299)

我尝试给当前目录和所有子目录中所有不是.sh文件的文件添加前缀bash using find
问题是我得到了一个错误:

mv: cannot move './test.txt' to 'PRE_./test.txt': No such file or directory

我的一句俏皮话是:

find -type f ! -name "*.sh" -exec sh -c 'mv "{}" PRE_"{}"' _ {} \;

我也尝试了xargsrename

find -type f ! -name "*.sh" -print0 | xargs -0 rename 's/(.*)$/PRE_$1/'

但我也犯了同样的错误。怎么了?先谢了!

pprl5pva

pprl5pva1#

find返回从.到文件的路径,因此在当前目录中开始搜索时,每个find结果都以./开头。因此,新文件名为PRE_./test.txt,即PRE_.目录中的test.txt。由于不存在PRE_.目录,mv无法将test.txt移动到该目录中,因此会显示您看到的错误消息。
如果您只重命名当前目录中的文件,而不是子目录中的文件,则可以使用bash:

shopt -s extglob 
for f in !(*.sh) ; do [[ -d "$f" ]] || mv "$f" "PRE_$f" ; done

感谢bash中!(pattern)结构的this answer,当extglob启用时可用,它返回所有与pattern不匹配的文件名。
对于所有子目录中的文件,也用途:

shopt -s extglob globstar
for f in **/!(*.sh) ; do [[ -d "$f" ]] || mv "$f" "${f%/*}/PRE_${f##*/}" ; done

多亏了globstar的this answer%##将路径组件截断,并将PRE_粘贴到正确的位置,即文件名的开头。

编辑上述两个选项中的[[ -d "$f" ]] ||可防止循环重命名目录。

8xiog9wr

8xiog9wr2#

最好不要在sh -c的参数中直接使用{},而是将其值作为参数传入。然后,您可以像往常一样使用参数扩展操作来修改其值。这里,我们将把参数拆分为目录和文件名组件,然后将它们重新组合,包括文件名前缀PRE_,以用作mv的参数。

script='
d=${1%/*}
f=${1#$d}
mv "$1" "$d/PRE_$f"
'
find -type f ! -name "*.sh" -exec sh -c "$script" _ {} \;

(This只是你最初尝试的一个小小的改变你传递了{}作为参数,但没有使用它,而是将值直接“嵌入”到传递给sh的字符串中。)
您还可以使用-exec +表单来最小化对sh的调用次数,方法是传递多个文件名并在shell中迭代它们。(这开始与@cxw建议的纯bash解决方案收敛,但保持POSIX以及bash 3.x的兼容性):

script='
for arg;
 d=${arg%/*}
 f=${arg#$d}
 mv "$1" "$d/PRE_$f"
done
'
find -type f ! -name "*.sh" -exec sh -c "$script" _ {} +
pu3pd22g

pu3pd22g3#

如果您不想更改子目录中的文件,可以使用以下命令:

find -type f ! -name "*.sh" -printf "%f\n" | xargs -r rename 's/(.*)$/PRE_$1/'

问题是文件名前面的./。

vxqlmq5t

vxqlmq5t4#

find -type f ! -name "*.sh" -exec rename -n 's|.*/\K|PRE_|' {} +
  • .*/匹配到文件名中的最后一个/
  • 通过使用\K lookbehind,在这种情况下我们可以避免捕获组的需要

显示正确重命名后,从rename中删除-n选项

w6lpcovy

w6lpcovy5#

在许多Linux发行版中,rename命令默认不可用。如果您的系统缺少rename命令,请使用以下命令安装:
对于Ubuntu和Debian,使用sudo apt安装重命名
对于CentOS和Fedora,使用sudo yum安装预命名

相关问题