Shell-Script

使用可能帶有空格的文件名列表的 POSIX 兼容方式

  • November 18, 2014

我已經看到 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 withset -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.

請記住始終在變數替換周圍加上雙引號,除非您明確希望發生欄位拆分(以及萬用字元,除非您已將其關閉)。

引用自:https://unix.stackexchange.com/questions/102891