Mailx 使用通配符附加多个文件

Mailx 使用通配符附加多个文件

我正在寻找 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,这是最好的版本,因为它适用于任何文件名。虽然打字有点多,但这是值得的。最好以防御性的方式编写脚本(和俏皮话),始终保持“会出什么问题吗?”牢记在心并确保不会发生。

相关内容