我有一个目录config
,其中包含以下文件:
$ ls config
file one
file two
file three
我想要一个bash脚本,当没有参数时,它会迭代所有这些文件;当给定文件名作为参数时,我希望它迭代命名文件。
#!/bin/sh
for file in ${@:-config/*}
do
echo "Processing '$file'"
done
如上所述,for循环中列表术语没有引号,它在无参数情况下产生预期输出,但在传递参数时断开(它在空格上分割文件名。)引用列表term(for file in "${@:-config/*}"
)在我传递文件名时起作用,但如果不这样做则无法扩展glob。
有没有办法让两种情况都有效?
答案 0 :(得分:3)
对于更简单的解决方案,只需修改IFS变量
即可#!/bin/bash
IFS=''
for file in ${@:-config/*}
do
echo "Processing '$file'"
done
IFS=$' \n\t'
$IFS
是一个默认的shell变量,它列出了shell使用的所有分隔符。如果从此列表中删除空格,则shell将不再分割为空格。您应该在运行后将其设置回默认值,这样它就不会导致其他函数在您的脚本中稍后行为错误
注意:这似乎与破坏行为不一致(我使用了debian,以及#!/bin/sh
指向破折号的链接)。如果使用空$IFS
,则传递的args将仅返回1个文件。但是,如果您输入一些随机值(即IFS=':'
),行为将是您想要的行为(除非您的文件名中有:
)
这适用于#!/bin/bash
,但
答案 1 :(得分:2)
如果没有给出位置参数,则显式设置;然后for循环对于两种情况都是相同的:
[ $# -eq 0 ] && set -- config/*
for file in "$@"; do
echo "Processing '$file'"
done
答案 2 :(得分:1)
将处理代码放在一个函数中,然后使用不同的循环来调用它:
if [ $# -eq 0 ]
then for file in config/*
do processing_func "$file"
done
else for file in "$@"
do processing_func "$file"
done
fi