Linux 如果没有这样的文件,则输出错误
我试图找出特定类型的文件的数量。若文件存在,那个么这个脚本工作正常,否则for循环执行一次(预计不会运行)Linux 如果没有这样的文件,则输出错误,linux,bash,shell,Linux,Bash,Shell,我试图找出特定类型的文件的数量。若文件存在,那个么这个脚本工作正常,否则for循环执行一次(预计不会运行) 可能还有其他方法来实现相同的功能,如ls*.txt | xargs…。但是作为一个新手,我想知道在发布的脚本中的问题。我请求你分享你在这方面的知识 当模式*.txt没有匹配文件时,它被解释为文本字符串“*.txt”。这就是为什么循环至少运行一次 有几种方法可以解决这个问题。您可以添加对匹配文件存在性的检查,如下所示: if ls *.txt >/dev/null 2>&
可能还有其他方法来实现相同的功能,如
ls*.txt | xargs…
。但是作为一个新手,我想知道在发布的脚本中的问题。我请求你分享你在这方面的知识 当模式*.txt
没有匹配文件时,它被解释为文本字符串“*.txt”
。这就是为什么循环至少运行一次
有几种方法可以解决这个问题。您可以添加对匹配文件存在性的检查,如下所示:
if ls *.txt >/dev/null 2>&1; then
for i in *.txt; do
...
done
fi
根据您希望在循环中执行的操作,您还可以使用find
:
find . -maxdepth 1 -name "*.txt" | while read i; do
...
done
但是,有些东西无法使用此构造(例如递增$j
),因为while
循环在子shell中运行,因此当子shell退出时(即循环终止),对$j
的所有更改都将丢失
作为旁注:我会将
$j
的增量从j=`expr$j+1`
更改为((j++)
脚本中没有问题,实际上,除了可以使用现代内置语言以更好的风格编写,而且如果没有文本文件,它会失败,请参见下文
echo "Checking for text files..."
j=0
for i in *.txt; do
echo "$i"
((++j))
done
if ((j!=0)); then
echo "No. of Text files: $j"
else
echo "No Text files."
fi
使用globbing时,最好使用failglob
的nullglob
如果无法扩展glob,将引发错误failglob
- 如果没有合适的扩展,
只会扩展为零nullglob
*.txt
将扩展为*.txt
(逐字),这正是您想要避免的
在你的情况下,把
shopt -s nullglob
在你的脚本顶端,你就完成了
现在,计算*.txt
文件数量的一种可能方法是:
shopt -s nullglob
a=(*.txt)
echo "There are ${#a[@]} text files"
关于
nullglob
和failglob
有什么大惊小怪的
让我们进入一个临时目录:
$ mkdir scratch; cd scratch
$ # this dir is empty
$ echo *.txt
*.txt
$
因为glob在那里没有合适的扩展。现在:
$ shopt -s nullglob
$ echo *.txt
$
因为nullglob
。现在我们将取消设置nullglob
并设置failglob
:
$ shopt -u nullglob
$ shopt -s failglob
$ echo *.txt
bash: no match: *.txt
$
明白了吗
底线是:每次使用globbing-in时,使用failglob
或nullglob
使脚本更加健壮
底线是:每次你使用globing而不使用failglob
或nullglob
,上帝就会杀死一只小猫
如果您想了解有关shopt和shell可选行为的更多信息,请参考。您真的需要脚本吗?像
ls-l*.txt | wc-l
这样的东西不管用吗?我刚刚开始学习shell脚本。不管怎样,我也要试试这个。但是这个脚本可能会有什么问题呢?一个风格提示:行尾不需要分号。但我没有得到nullglob的东西。无论如何,我会学习的。:)@Jeyaram看到我的编辑,试图澄清nullglob
和failglob
。所以这些都是bash变量。有趣。谢谢:)@Jeyaram不,不是变量。请参阅。这里它被称为特殊bash变量。这就是我提到bash变量的原因。无论如何,我会参考链接。解析find
的输出通常不是一个好主意。同样在这里,while
循环将在子shell中执行,因此如果您在子shell中执行(++j))
,子shell退出后将看不到它。我不是在这里解析find
输出,只是逐行读取它。怎么了?不过,关于增加$j
,您是对的。我已更新了答案。如果文件名包含换行符,则是错误的。尝试:触摸\n在\its\name.txt'
中出现断线的文件$'!此外,由于read
会丢弃行首和行尾的空格,因此在某些情况下可能会出现问题。有好习惯也有坏习惯。大多数坏习惯可能在99.9%的时间里有效,但一旦坏习惯打破,情况就糟糕了。逐行读取find
的输出实际上就是我所说的解析其输出。但我可能错了<代码>:)如果[-f*.txt]
在多个文件匹配“*.txt”的情况下因“参数太多”而失败,因此第一种方法实际上不起作用。
$ shopt -u nullglob
$ shopt -s failglob
$ echo *.txt
bash: no match: *.txt
$