hig*_*guy 8 bash wildcards arguments glob
我有以下简化的 bash 脚本
#!/bin/bash
files=("$@")
if [ "X$files" = "X" ]; then
files=$HOME/print/*.pdf;
fi
for file in "${files[@]}"; do
ls "$file";
done
Run Code Online (Sandbox Code Playgroud)
如果我将参数(文件名)作为参数传递,该脚本将打印正确的文件名。另一方面,如果我不传递参数,它会打印
/home/user/print/*.pdf: No such file or directory
Run Code Online (Sandbox Code Playgroud)
为什么在这种情况下文件名没有扩展,我该如何解决?请注意,我使用files=("$@")
and"${files[@]}"
结构是因为我读到它比通常的“files=$*”更受欢迎。
Sté*_*las 10
您将分配files
为标量变量而不是数组变量。
在
files=$HOME/print/*.pdf
Run Code Online (Sandbox Code Playgroud)
你分配一些字符串一样/home/highsciguy/print/*.pdf
的$files
标量(又名字符串)变量。
用:
files=(~/print/*.pdf)
Run Code Online (Sandbox Code Playgroud)
或者
files=("$HOME"/print/*.pdf)
Run Code Online (Sandbox Code Playgroud)
反而。shell 会将该通配模式扩展为文件路径列表,并将它们中的每一个分配给$files
数组的元素。
glob 的扩展在赋值时完成。
您不必使用非标准的 sh 功能,您可以通过编写它来使用您的系统sh
而不是bash
这里:
#!/bin/sh -
[ "$#" -gt 0 ] || set -- ~/print/*.pdf
for file do
ls -d -- "$file"
done
Run Code Online (Sandbox Code Playgroud)
set
是分配"$@"
位置参数数组。
另一种方法可能是将通配模式存储在标量变量中:
files=$HOME/print/*.pdf
Run Code Online (Sandbox Code Playgroud)
并让 shell 在$files
变量扩展时扩展 glob 。
IFS= # disable word splitting
for file in $files; do ...
Run Code Online (Sandbox Code Playgroud)
在这里,因为$files
没有被引用(你通常不应该这样做),它的扩展会受到分词(我们在这里已经禁用)和通配符/文件名生成的影响。
因此*.pdf
将扩展为匹配文件的列表。但是,如果$HOME
包含通配符,它们也可以被扩展,这就是为什么仍然最好使用数组变量的原因。