bash:脚本和终端中的不同行为(循环文件)

bash:脚本和终端中的不同行为(循环文件)

我正在尝试根据我与 case 语句一起使用的文件夹来循环具有不同搜索条件的文件。基本上是:

#!/bin/bash
case folder in
  "Testordner")
     search_filename=*_0_*.txt
      ;;
  "Ordner2")
     search_filename=*_65_*fg*.txt
     ;;
  *)
     ;;
esac
for files in $search_filename; do
  echo $files
done

我原本希望在最后的回声中获得符合搜索标准的文件列表。相反,我得到了搜索标准本身。

为了测试,我F="*.txt";for files in $F;do echo $files;done直接在 bash 中尝试(它有效,我得到了文件列表)和同一个脚本(这让我得到了输出)*.txt 已经尝试了不同的变量扩展内容(例如$(..) ((..)) ${..},所有这些都不起作用。)

这是为什么?我该如何解决?

找到帮助会很高兴。最美好的祝愿卡罗


使用 Ubuntu 22.04LTS、KDE/plasma 桌面; bash v5.1.16(1)。终端:konsole v21.12.3

答案1

在 Bash 中,如果nullglob禁用(通常是默认值),在没有匹配的情况下,全局模式将计算/扩展为自身(例如,*.txt计算为文字 string *.txt)。启用后nullglob(通常更适合脚本),在没有匹配的情况下,全局模式将计算/扩展为空字符串。

如果您的脚本从不同的目录运行,您的 glob 将以不同的方式扩展(当然,除非每个目录中都存在相同的文件名)。

例如:

user@host:~ 0 $ touch {a,b,c}.log
user@host:~ 0 $ ls -l
total 0
-rw-------  1 user  staff  0 Jul 25 10:27 a.log
-rw-------  1 user  staff  0 Jul 25 10:27 b.log
-rw-------  1 user  staff  0 Jul 25 10:27 c.log
user@host:~ 0 $ shopt nullglob
nullglob        off
user@host:~ 1 $ echo *.log
a.log b.log c.log
user@host:~ 0 $ echo *.bak
*.bak
user@host:~ 0 $ shopt -s nullglob
user@host:~ 0 $ shopt nullglob
nullglob        on
user@host:~ 0 $ echo *.log
a.log b.log c.log
user@host:~ 0 $ echo *.bak

user@host:~ 0 $ 

在一个不相关的注释上……也许可以考虑将故意引用习惯化,至少在适当的时候;例如,echo "$files",而不是echo $files提高命令行安全性和空白处理。

如果有兴趣,也可能需要使用数组;例如,

#!/bin/bash -e

export PATH=/bin:/sbin:/usr/bin:/usr/sbin
shopt -s nullglob

declare -a files=()
case "$1" in
    'logs')
        files=(*.log)
        ;;
    'baks')
        files=(*.bak)
        ;;
    *)
        echo 'invalid argument' 1>&2
        exit 1
        ;;
esac

for f in "${files[@]}"; do
    echo "$f"
done

相关内容