对脚本编写非常陌生。我有一个目录,其中包含一些文本文件,还有一些文本文件还包含附加扩展名 ( ) ,.xfr
例如, , , 。file1.txt
file2.txt.xfr
file3.txt
file4.txt.xfr
尝试编写 bash 脚本来检查目录,如果文件包含.xfr
(删除扩展名),则重命名该文件,然后根据结果写出日志条目。
我可以编写一个脚本来重命名文件,但是当涉及到这if
部分时,我很挣扎。这是有效的部分:
#!/bin/bash
for file in ~/Test/Files/*.xfr
do
mv "$file" "${file%.xfr}"
echo "$file has been resent" > ~/Test/log.txt
done
要添加if
,我认为这会起作用,但遗憾的是不行:
#!/bin/bash
if [[ ! -e ~/Test/Files/*.xfr ]]
then
mv "$file" "${file%.xfr}"
echo "$file has been renamed" > ~/Test/log.txt
else
echo "no files were renamed" ~/Test/log.txt
fi
任何帮助将不胜感激。
更新:脚本已更新为使用变量代替文件路径,现在看起来像这样:
#!/bin/bash
PATH='/home/davrog/Test/Files'
LOG='/home/davrog/Test/log.txt'
for file in $PATH/*.xfr
do
if [ -e $PATH/$file ]
then
mv "$file" "${file%.xfr}"
echo "$(date) $file has been resent"
else
echo "$(date) no files were stuck when check was run"
fi
done >>$LOG
这似乎破坏了 mv 函数,我怀疑是因为它试图将文件重命名回当前名称。看看其他帖子, mv 函数看起来是正确的,所以不知道如何解决这个问题。预先感谢您的任何帮助。
答案1
稍微修改一下你的第一个脚本:
#!/bin/bash
for file in ~/Test/Files/*.xfr
do
if [ ! -e "$file" ]; then
echo 'no files were renamed'
break
fi
mv "$file" "${file%.xfr}"
echo "$file has been renamed"
done > ~/Test/log.txt
我在这里做了两件事:
重定向到日志文件会在每次迭代中截断日志文件,因此我将其移至末尾,
done
以便它重定向循环的所有标准输出。如果该模式与任何文件名都不匹配,则默认情况下它将保持不展开状态。我通过
-e
测试检测到这一点并输出一条特殊消息。然后我就break
退出了循环。
选择:
#!/bin/bash
for file in "$HOME/Test/Files"/*.xfr
do
if [ -e "$file" ]; then
mv "$file" "${file%.xfr}"
printf '%s has been renamed\n' "$file"
else
echo 'no files were renamed'
fi
done >"$HOME/Test/log.txt"
在这里,我只是稍微改变了流程并用来$HOME
代替波形符(恕我直言,在脚本中看起来更好)。我也使用printf
代替,echo
因为它通常对于输出变量数据更安全(参见例如“为什么 printf 比 echo 更好?”)。
上述两种替代方案也可以使用/bin/sh
而不是运行/bin/bash
。
如果您想编写更多“报告”,还有另一种选择:
#!/bin/bash
shopt -s nullglob
xfr_files=( "$HOME/Test/Files"/*.xfr )
for file in "${xfr_files[@]}"; do
mv "$file" "${file%.xfr}"
done
printf '%d files renamed\n' "${#xfr_files[@]}"
if [ "${#xfr_files[@]}" -gt 0 ]; then
printf '\t%s\n' "${xfr_files[@]}"
fi
这设置了nullglob
shell 选项,bash
如果没有匹配项,则模式将扩展为空。然后它会写出重命名的文件数,如果该数字大于零,它还会列出带有制表符缩进的文件名。
在您更新的问题中,您使用变量PATH
.这恰好是保存 shell 实用程序搜索路径的变量,将其设置为:
除 - 分隔的目录列表之外的任何内容可能会使 shell 无法找到mv
其他常用工具。
一般来说,避免在 shell 脚本中使用大写变量名,而使用小写或可能混合大小写的变量。这样,您就可以避免意外覆盖 shell 可能使用的重要变量。
此外,[ -e $PATH/$file ]
测试应读取[ -e "$file" ]
为路径已包含在 的值中$file
。这也是我在上面的代码中使用的。不要忘记对所有变量扩展加双引号!
答案2
如果你已经prename
安装了,你可以按照以下方式运行一些东西
prename 's/\.xfr$// and print "$_ resended\n"' ~/test/* > f.log