我写了一个脚本,一次重命名几个文件并添加前导零。 该脚本将要重命名的文件作为第一个参数,第二个是新名称,作为第三个参数,您可以提供新的扩展名
只要文件不包含空格(测试asd 1.txt / test asd 2.txt),它实际上是有效的,因为输出是:
~/Desktop $ gpRenameWithZero test\ asd\* test_ mp3
ls: cannot access test: No such file or directory
ls: cannot access asd*: No such file or directory
ls: cannot access test: No such file or directory
ls: cannot access asd*: No such file or directory
这是脚本:
#!/bin/bash
#rename a group of files with adding padding zero: gpRenameWithZero $1=filesToBeRenamed $2=newName $3=filetype: gpRenameWithZero \* newName_ jpg
#123 files -> length of number are 3 digits
numberOfDigits=$(ls $1| wc -l | xargs expr length)
#take extension from command line or take from filename
if [ $# -gt 2 ]; then
extension=$3
else
extension=$(ls -rt $1 | head -n 1 | rev | cut -d . -f1 | rev)
fi
#Preview
ls -rt $1 | cat -n | while read n f; do echo mv "$f" `printf "$2%0$numberOfDigits"d".$extension" $n`; done
read -p "Do you wish to rename [y/n]?" yn
case $yn in
[Yy]* ) ls -rt $1 | cat -n | while read n f; do mv "$f" `printf "$2%0$numberOfDigits"d".$extension" $n`; done;;
[Nn]* ) ;;
esac
我已经尝试过引用/双引用vriables和参数,转义/不转义。
如何解决此案?或者是否有一个更简单的脚本,它将文件重命名,新名称和扩展名作为参数)来重命名多个文件。
答案 0 :(得分:0)
你明白了,为什么是真的,评论说的是:不要解析ls
的输出。
在这种情况下,您需要处理以NULL结尾的文件名。以下是许多可以使用这种以NULL结尾的字符串的命令。
find
命令可以使用arg -print0
或精确指定的-print "<format>\0"
输出以NULL结尾的文件名。
因为你想要排序(数字)文件的修改时间(ls -rt
),你需要使用一些技巧。所以
find
命令(GNU版本)可以打印出文件修改时间这可以通过下一个命令来实现:
find . -mindepth 1 -maxdepth 1 -name "*" -printf "%T@:%p\0" |sort -zrn |sed -z 's/[^:]*://'
^^^^^^^^ ^^^ ^^^^^^^^^^
modification-time-in-seconds<colon>path-name<NULL>---+ | |
sort the NULL-terminated lines numerically (by time) ---+ |
remove the <time><colon> part, so only the filename remains ----------+
您可以将上述内容放入bash函数中以便于使用,例如:
sort_files_by_time() {
find "${1:-.}" -mindepth 1 -maxdepth 1 -type f -name "${2:-*}" -printf "%T@:%p\0" | sort -zrn | sed -z 's/[^:]*://'
}
上述功能可以采用两个可选参数:
现在你有一个NULL终止的排序文件名列表,需要阅读并使用它们。下一个循环
while IFS= read -d $'\0' -r path ; do
dir=$(dirname "$path")
file=$(basename "$path")
#do what you want
done < <(sort_files_by_time)
总是双引号&#34; $ variables&#34;什么可以包含空格。
答案 1 :(得分:0)
在Unix中,命令行参数的通配符扩展由shell执行 - 然后传递给程序。
即使文件名中没有空格,此脚本也不起作用。例如,如果有三个文件 song1.mp3 , song_2.MP3 和 song_0003.mpeg3 ,则运行gpRenameWithZero song* test_ mp3
脚本将传递五个参数:$ 1将是&#34; song1.mp3&#34;,$ 2将是&#34; song_0003.mpeg3&#34;,$ 3将是&#34; song_2.MP3&#34;,$ 4将是&#34;测试_&#34;而$ 5将是&#34; mp3&#34;。所以你的脚本中的1美元不是你所期望的。
最好将新文件名前缀和扩展名视为第一个和第二个参数,然后剩下的参数(无论有多少个)将是文件名。更高级的解决方案甚至可以将它们解析为单独的选项,因此所有参数都是文件名(即第一个和第二个参数的处理方式不同)。
#!/bin/sh
# Usage: renameFiles prefix extension {filenames}
# First argument is the new file name prefix
PREFIX=$1
shift
# Second argument is the new file name extension
EXT=$1
shift
# Calculate the maximum width of the number in the new file names
TMP=`echo $# | wc -c`
NUMBER_OF_DIGITS=`expr $TMP - 1` # Because TMP also counts the newline character
# Process all the remaining arguments as file names
COUNT=1
for FILE in "$@"
do
NEW_NAME=`printf "${PREFIX}%0${NUMBER_OF_DIGITS}d.${EXT}" $COUNT`
# If you wish, prompt the user here
mv "$FILE" "$NEW_NAME"
COUNT=`expr $COUNT + 1`
done
#EOF
如果任何参数文件名包含空格,则需要围绕$ @的双引号和 mv 命令的第一个参数才能使脚本正常工作。如果前缀和/或扩展名包含空格,则脚本需要在 mv 命令的第二个参数周围加上双引号。