Shell-Script
使用可能帶有空格的文件名列表的 POSIX 兼容方式
我已經看到 Bash 腳本指南建議使用數組來處理包含空格的文件名。然而, DashAsBinSh建議數組不可移植,因此我正在尋找一種兼容 POSIX 的方式來處理可能包含空格的文件名列表。
我正在尋找修改下面的範例腳本,以便它會
echo
foo/target/a.jar foo/target/b.jar bar/target/lol whitespace.jar
這是腳本
#!/usr/bin/env sh INPUT="foo/target/a.jar foo/target/b.jar bar/target/b.jar bar/target/lol whitespace.jar" # this would be produced by a 'ls' command # We can execute the ls within the script, if it helps dostuffwith() { echo $1; }; F_LOCATIONS=$INPUT ALL_FILES=$(for f in $F_LOCATIONS; do echo `basename $f`; done) ALL_FILES=$(echo "$ALL_FILES" | sort | uniq) for f in $ALL_FILES do fpath=$(echo "$F_LOCATIONS" | grep -m1 $f) dostuffwith $fpath done
POSIX shell 有一個數組:位置參數(
$1
、$2
等,統稱為"$@"
)。set -- 'foo/target/a.jar' 'foo/target/b.jar' 'bar/target/b.jar' 'bar/target/lol whitespace.jar' set -- "$@" '/another/one at the end.jar' … for jar do dostuffwith "$jar" done
這是不方便的,因為只有一個,它破壞了位置參數的任何其他用途。位置參數是函式的局部參數,這有時是一種祝福,有時是一種詛咒。
如果保證文件名不包含換行符,則可以使用換行符作為分隔符。展開變數時,首先關閉 globbing with
set -f
並將欄位拆分字元列表設置為IFS
僅包含換行符。INPUT="foo/target/a.jar foo/target/b.jar bar/target/b.jar bar/target/lol whitespace.jar" … set -f; IFS=' ' # turn off variable value expansion except for splitting at newlines for jar in $INPUT; do set +f; unset IFS dostuffwith "$jar" # restore globbing and field splitting at all whitespace done set +f; unset IFS # do it again in case $INPUT was empty
通過換行符分隔列表中的項目,您可以有效地使用許多文本處理命令,尤其是
sort
.請記住始終在變數替換周圍加上雙引號,除非您明確希望發生欄位拆分(以及萬用字元,除非您已將其關閉)。