删除文件扩展名(如果存在)

删除文件扩展名(如果存在)

对脚本编写非常陌生。我有一个目录,其中包含一些文本文件,还有一些文本文件还包含附加扩展名 ( ) ,.xfr例如, , , 。file1.txtfile2.txt.xfrfile3.txtfile4.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

我在这里做了两件事:

  1. 重定向到日志文件会在每次迭代中截断日志文件,因此我将其移至末尾,done以便它重定向循环的所有标准输出。

  2. 如果该模式与任何文件名都不匹配,则默认情况下它将保持不展开状态。我通过-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

这设置了nullglobshell 选项,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

相关内容