繁体   English   中英

如何修复在命令行工作的 shell 脚本? 脚本使用 `mv`、引号、参数扩展和变量

[英]How to fix shell script that works at the command line? Script uses `mv`, quotation marks, parameter expansion, and variables

我在一个目录中有一组文件。 一些文件名包含八位数的日期,如下所示:

test_file_20220101.txt
...
test_file_20220110.txt

我想使用 shell 脚本来重命名它们,使日期带有破折号,如下所示:

test_file_2022-01-01.txt
...
test_file_2022-01-10.txt

我有一些 shell 代码(大部分)在命令行上运行良好(一旦echo被删除*):

for f in ./*; 
do suffix="${f##*[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]}"; 
number="${f%"$suffix"}"; 
number="${number##*[\!0-9]}"; 
year="${number:0:4}"; 
month="${number:4:2}"; 
day="${number:6:2}"; 
echo mv "$f" "${f/$number/$year-$month-$day}"; 
done

但是,当我在开头添加#!/bin/sh#!/bin/bash#!/bin/zsh时,将其保存为脚本(具有执行权限)并运行脚本,它不会影响文件名更改,我在stdout得到这个:

echo mv ./test_file_20220110 ./test_file_20220110

* 移除回声没有任何改变; 不希望的结果与 shell 脚本相同。 我不相信回声是问题所在。

我也尝试过,但没有成功:用 ' 替换所有'或用' 删除所有引号 所有组合都会产生相同的错误脚本输出。 添加set -v运行脚本的输出对我没有帮助,但它是:

+ for f in './*'
+ suffix=
+ number=./test_file_20220101
+ number=
+ year=
+ month=
+ day=
+ echo mv ./test_file_20220101 ./test_file_20220101
mv ./test_file_20220101 ./test_file_20220101
... [etc.]

配置:

  • 默认外壳: zsh
  • macOS 12.1“蒙特雷”

另外,作为一项额外的改进,我想解决一个事实,即一些没有预期的八位数模式的文件最终被重命名为--other_filename.txt类的东西。 在 CLI 中使用上述命令后,我单独使用以下命令来成功修复此问题。

for f in *; do echo mv -- "$f" "${f##--}"; done

如果这个“cleanup”命令可以与上一次“cleanup”扫描在同一个脚本中,那就太好了。

set -v输出可能对您没有帮助,但它告诉脚本在尝试从文件名中提取数字时会横向移动。 至少在 bash 中,那是因为您引用了! 在你的括号表达式中。 也就是说, [\!0-9]匹配集合 '!'、'0'、'1'、...'9' 中的一个字符,这不是您想要的。

您应该在命令行中遵守相同的规定,如果您不这样做,那么我无法解释。

您脚本的这种变化对我有用:

#!/bin/bash

for f in ./*; do
  suffix=${f##*[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]}
  number=${f%"$suffix"}
  number=${number##*[!0-9]}
  year=${number:0:4}
  month=${number:4:2}
  day=${number:6:2}
  echo mv "$f" "${f/${number}/${year}-${month}-${day}}"
done

(除了对括号表达式的更正之外的更改是风格上的,而不是功能性的。)

这个Shellcheck -clean 代码演示了另一种方法:

#! /bin/bash -p

date_rx='([[:digit:]][[:digit:]][[:digit:]][[:digit:]])([[:digit:]][[:digit:]])([[:digit:]][[:digit:]])'
date_file_rx="(.*)${date_rx}(.*)"

for file in *; do
    if [[ $file =~ $date_file_rx ]]; then
        prefix=${BASH_REMATCH[1]}
        year=${BASH_REMATCH[2]}
        month=${BASH_REMATCH[3]}
        day=${BASH_REMATCH[4]}
        suffix=${BASH_REMATCH[5]}
        echo mv -n -v -- "$file" "${prefix}${year}-${month}-${day}${suffix}"
    fi
done

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM