Luk*_*keB 2 bash shell-script wildcards
我正在练习shell 脚本,并尝试制作一个简单的脚本,该脚本将目录作为参数,循环遍历其中的每个文件并打印出其名称和大小。
\n#!/bin/bash\n# A practice shell script to try and display a list of file names\n# and their sizes using the output of ls -l and cut.\ndeclare -i index\nexport index=0\nexport name=""\nexport size=0\n\nfor file in $1 ; do\n index+=1\n name=`basename $file`\n size=`ls -l $file | cut -d " " -f 5`\n echo "$index: $name, size: $size bytes"\ndone\n
Run Code Online (Sandbox Code Playgroud)\n当我./*
作为参数给出时,它会针对一个文件执行此操作,仅此而已。但是,如果我编辑上面的代码并将其放在./*
的位置$1
,它就会工作并循环当前目录中的所有文件。
为什么\xe2\x80\x99 不会做同样的事情,什么时候$1
应该等于./*
?
Adm*_*Bee 10
原因是调用脚本的 shell 在传递给脚本./*
之前扩展了通配模式。这意味着,如果您的通配模式与例如匹配file1.txt
,file4.txt
则将脚本调用为
./my_script.sh ./*
Run Code Online (Sandbox Code Playgroud)
实际上会被解释为
./my_script.sh file1.txt file2.txt file3.txt file4.txt
Run Code Online (Sandbox Code Playgroud)
这些将是 shell 脚本看到的参数。
如需进一步阅读,请查看Bash 参考手册中有关 shell 扩展顺序的部分。
有两种可能性可以解决该问题:
for f in "$1"/*
do
# operations on "$f"
done
Run Code Online (Sandbox Code Playgroud)
for f in "$@"
do
# operations on "$f"
done
Run Code Online (Sandbox Code Playgroud)
如果您想通过将 glob 模式传递到脚本中来实现这一点 - 这当然是一个有趣的练习 - 这也是可能的(请参阅 @ilkkachu 的评论)。正如 @fra-san 在评论中提到的,该方法具有优点 - 它可以为脚本使用增加更多灵活性,并且它规避了 shell 命令行参数的限制(参见“参数列表太长”;尽管 RAM 会仍然限制结果文件名列表的长度) - 但需要您格外小心。
./my_script.sh "./*"
./my_script.sh './*'
./my_script.sh ./\*
Run Code Online (Sandbox Code Playgroud)
$1
在脚本内部,您将引用不带引号的位置参数,以便它实际上由 shell 解释(这是我们经常想要避免的)。IFS
设置为空字符串,以确保不会发生分词。for
看起来像
IFS=
for f in $1
do
# Operations on "$f"
done
Run Code Online (Sandbox Code Playgroud)
ls
解析的输出。如果您想识别特定文件的属性,该工具是更好的选择。为了确定文件的大小,例如,您可以使用
stat
size=$(stat --printf="%s" "$f")
Run Code Online (Sandbox Code Playgroud)
$( ... )
而不是旧的“反引号样式” ` ... `
。shellcheck
,在许多 Linux 发行版中也可以作为独立工具使用,以防止这种(和其他)可能的错误源。 归档时间: |
|
查看次数: |
2790 次 |
最近记录: |