我正在寻找 Unix 脚本,我可以在其中附加多个具有相似名称的文件。
例如,在服务器上我有以下文件:
output2019_1.txt
output2019_2.txt
output2019_3.txt
output2020_1.txt
echo "Hello" | mailx -a "test attachments" -a output2019* [email protected]
上述脚本仅附加 2019 年的一个文件。我希望 2019 年的所有 3 个文件都应附加到电子邮件中。
请我正在寻找实际的附件,而不是电子邮件正文中过去的一些 uuencode。
答案1
您可以通过以下方式使用大括号扩展:
echo "Hello" | mailx -a "test attachments" '-aoutput2019_'{1..3}.txt [email protected]
答案2
您可以使用printf
和命令替换:
echo Hello | mailx $(printf -- '-A %s ' output2019*) [email protected]
告诉--
printf 没有更多的选项参数(否则它会抱怨-A
选项无效)。是'-A %s '
格式字符串,每个剩余的参数(匹配的文件output2019*.txt
)将使用该格式打印。例如 mailx 将运行为:
mailx -A output2019_1.txt -A output2019_2.txt -A output2019_3.txt [email protected]
注意:这不适用于所有文件名 - 对于包含空格或 shell 元字符的文件名,它将失败。为了解决这些问题,您可以在格式字符串中嵌入引号。例如
echo Hello | mailx $(printf -- "-A '%s' " output2019*) [email protected]
这适用于包含任何字符的文件名除了单引号。
处理包含以下内容的文件名任何有效字符,您必须首先创建一个包含多对 -A 选项和文件名的数组。例如使用流程替代在bash
:
mapfile -d '' -t attachments < \
<(find . -maxdepth 1 -name 'output2019*' -printf '-A\0%p\0')
echo Hello | mailx "${attachments[@]}" [email protected]
当bash像这样扩展一个数组时(即用双引号括起来,作为[@]
索引),数组的每个元素被视为一个单独的“单词”,并且不受任何进一步的分词或解释的影响。
这需要 GNU find
(Linux 上的标准)作为-printf
选项。在这里,我们告诉find
每个文件名输出-A
一个 NUL,然后文件名后面跟着另一个 NUL。
该mapfile
命令从 stdin 填充一个数组,我们告诉它 NUL 是分隔符(带有)...并且 stdin通过进程替换-d ''
重定向(<
) 。find ...
请help mapfile
参阅 bash。顺便说一句,是bashreadarray
的同义词。mapfile
使用示例中的文件名,这将$attachments
使用 6 个元素填充数组:
$ declare -p attachments
declare -a attachments=([0]="-A" [1]="./output2019_1.txt" [2]="-A" [3]="./output2019_3.txt" [4]="-A" [5]="./output2019_2.txt")
IMO,这是最好的版本,因为它适用于任何文件名。虽然打字有点多,但这是值得的。最好以防御性的方式编写脚本(和俏皮话),始终保持“会出什么问题吗?”牢记在心并确保不会发生。