如何在bash循环列表中转义空格?
我有一个bash shell脚本循环通过某个目录的所有子目录(但不是文件)。问题是一些目录名称包含空格。
这里是我的测试目录的内容: $ls -F test Baltimore/ Cherry Hill/ Edison/ New York City/ Philadelphia/ cities.txt 和循环通过目录的代码: for f in `find test/* -type d`; do echo $f done 这里是输出: test/Baltimore test/Cherry Hill test/Edison test/New York City test/Philadelphia 樱桃山和纽约市被视为2或3个单独的条目。 我试着引用文件名,像这样: for f in `find test/* -type d | sed -e 's/^/"/' | sed -e 's/$/"/'`; do echo $f done 但无济于事。 有一个简单的方法来做到这一点。 下面的答案是伟大的。但是为了使这更复杂 – 我不总是想使用我的test目录中列出的目录。有时候,我想将目录名称作为命令行参数传递。 我采取了Charles的建议设置IFS,并提出以下: dirlist="${@}" ( [[ -z "$dirlist" ]] && dirlist=`find test -mindepth 1 -type d` && IFS=$'n' for d in $dirlist; do echo $d done ) 这工作很好,除非在命令行参数中有空格(即使这些参数被引用)。例如,调用这样的脚本:test.sh“Cherry Hill”“New York City”生成以下输出: Cherry Hill New York City
首先,不要这样做。最好的办法是正确使用find -exec:
# this is safe find test -type d -exec echo '{}' + 另一个安全的方法是使用NUL终止列表,虽然这需要你找到支持-print0: # this is safe while IFS= read -r -d '' n; do printf '%qn' "$n" done < <(find test -mindepth 1 -type d -print0) 您还可以从find中填充数组,并稍后传递该数组: # this is safe declare -a myarray while IFS= read -r -d '' n; do myarray+=( "$n" ) done < <(find test -mindepth 1 -type d -print0) printf '%qn' "${myarray[@]}" # printf is an example; use it however you want 如果你的find不支持-print0,你的结果是不安全的 – 如果文件存在包含换行符的名称(这是,是合法的),下面的行为将不会如所期望的: # this is unsafe while IFS= read -r n; do printf '%qn' "$n" done < <(find test -mindepth 1 -type d) 如果一个人不打算使用上述之一,第三种方法(在时间和内存使用方面效率较低,因为它在字分割之前读取子过程的整个输出)是使用IFS变量不包含空格字符。关闭globbing(设置-f)以防止包含glob字符的字符串,如[],*或?从扩展: # this is unsafe (but less unsafe than it would be without the following precautions) ( IFS=$'n' # split only on newlines set -f # disable globbing for n in $(find test -mindepth 1 -type d); do printf '%qn' "$n" done ) 最后,对于命令行参数的情况,你应该使用数组,如果你的shell支持它们(即它的ksh,bash或zsh): # this is safe for d in "$@"; do printf '%sn' "$d" done 将保持分离。注意,引用(和使用$ @而不是$ *)很重要。数组也可以通过其他方式填充,如glob表达式: # this is safe entries=( test/* ) for d in "${entries[@]}"; do printf '%sn' "$d" done (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |