我目前正在处理格式化文件名。下面我有一个while循环,它运行文件名并用_
替换空格,并保留连字符后的任何内容。现在问题是循环遍历find
命令的结果以格式化名称。在脚本中运行时,输出如下:
find: paths must precede expression: rename
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
rename.sh
while read -r file
do
new_file=$(echo "$file" | sed -re 's/^([^-]*)-\s*([^\.]*)/\L\1\E-\2/' -e 's/ /_/g' -e 's/_-/-
/g')
echo "mv '$file' '$new_file'"
done < <(find ./ -type f rename)
之前的文件名:
'./My File - KeEp.txt'
文件名后:
'./my_file-KeEp.txt'
答案 0 :(得分:2)
您打算rename
在find ./ -type f rename
做什么?
find
正如错误消息告诉您的那样,将其解释为路径(搜索),然后告诉您不允许在参数之后添加路径。
话虽如此,正如@Beta在他的评论中指出的那样,在这里使用while
循环是不必要的(而且是脆弱的)。
请改为尝试:
find ./ -type f -exec bash -c 'echo "mv \"$1\" \"$(echo "$1" | sed -re '\''s/^([^-]*)-\s*([^\.]*)/\L\1\E-\2/'\'' -e '\''s/ /_/g'\'' -e '\''s/_-/-/g'\'')\""' - {} \;
或者这实际上是这样做的:
find ./ -type f -exec bash -c 'mv "$1" "$(echo "$1" | sed -re '\''s/^([^-]*)-\s*([^\.]*)/\L\1\E-\2/'\'' -e '\''s/ /_/g'\'' -e '\''s/_-/-/g'\'')"' - {} \;
稍微解释一下:
'\''
位是你如何在单引号字符串中转义单引号(你结束字符串,转义单引号并再次启动字符串)。-
中的- {}
用于填充$0
参数,该参数是使用bash
和其他参数运行时-c
的第一个参数。 (如果不这样,脚本需要使用$0
而不是$1
来访问文件名。)哦,你的原始脚本在你想要扩展的变量周围使用单引号,当你从echo命令中取出双引号时,它就不起作用了。
答案 1 :(得分:1)
我认为你的主要错误是&#34;重命名&#34; find命令的参数,我不明白为什么你把它放在那里。还有一些事情你也可以改进,例如不尝试重命名后面有相同名称的文件,而不是&#34; ./"你可以简单地写'#34;。&#34;。 另请注意,您的脚本不会在连字符之后保留任何内容&#34;因为即使在你的示例文件名中,它也会改变空格。
我仍然会使用while循环,因为每次重命名产生bash + sed都可以通过这种方式消除。我使用find的-name参数只处理包含连字符的文件名。
这样的事情:
while read -r file; do
x="${file%%-*}" # before first hyphen
y="${file#*-}" # after first hyphen
x="${x,,[A-Z]}" # make it lowercase
x="${x// /_}" # change all spaces to underscores
new_file="${x}-${y}"
if [ "$file" != "$new_file" ]; then
echo mv "$file" "$new_file"
fi
done < <(find . -type f -name '*-*')