我写了一个处理一些“常规”文件名的 shell 脚本,但我读过为什么我的 shell 脚本会因为空格或其他特殊字符而卡住?和为什么你不应该解析 ls 的输出我希望它更加强大并处理任何有效的文件名(和/或目录名)。如何创建文件和目录的测试台来运行我的脚本?
答案1
创建一个单独的目录来播放(主要是为了方便以后清理);$TMPDIR
如果已设置,则使用值,否则/tmp
:
mkdir "${TMPDIR-/tmp}/testing"
cd "${TMPDIR-/tmp}/testing"
创建独立的文件,但由于空格(空格、制表符、换行符、回车符、退格符)而显得彼此相似:
touch -- a b 'a ' 'b ' 'a b' 'a b' $'a\bb'
touch -- a$'\xe2\x80\x82'b a$'\xe2\x80\x83'b a$'\t'b a$'\n'b a$'\r'b
以上归功于帕特里克。两个十六进制代码是 UTF-8 空格分隔符,称为坚果和羊肉; “在双向上下文中,它充当空白并且不进行镜像。在某些情况下,该字形可能会与其他 20 个字形混淆。”
创建一个普通文件和一个如果被视为 glob 则将扩展到第一个文件的文件:
touch -- x '[x]'
以上归功于乌普斯·Q·温布利。
与此相类似:
touch -- 'a?b' 'a*b'
以上归功于戴夫·汤普森_085在这里的评论中。
touch -- foo\`echo\ malicious\`bar
以上归功于神客。
如果在 shell 上下文中求值,文件名将扩展为不同的内容(并且可能是任意执行!):
touch '$( echo boom )'
使用:
touch -- single\'quote double\"quote back\\slash
捕获将文件名放在引号中而不转义引号的尝试。
touch -- -a -b -c -r -R - a=x
以上归功于斯蒂芬·查泽拉斯。
创建命名管道和符号链接(以创建非“常规”文件):
mkfifo fifo
ln -s a alink
创建名称中包含各种空格的子目录,以及其中的令牌文件:
mkdir subdir "subdir 1" "subdir 2" "subdir 3 " subdir$'\n'4
touch subdir/file0 "subdir 1"/file1 "subdir 2"/file2 "subdir 3 "/file3 subdir$'\n'4/file4
创建仅包含*
(删除可能有问题)的文件名,仅包含(常规!)空格的文件名,死符号链接,循环到自身的符号链接以及带有返回父目录的链接的子目录:
touch -- '*' '**' '***' ' '
ln -s /does/not/exist dead
ln -s loop loop
mkdir subdir_with_link
(cd subdir_with_link && ln -s .. parent)
更多杂项文件名。最后两个是“小数斜杠”和“除法斜杠”的 unicode。
touch -- '(' '!' '!!' $'\xe2\x81\x84' $'\xe2\x88\x95'
想法来自斯科特:
touch -- '-' '--' ';' '&' '|' '<' '>' '$' ')' '{' '}' = \\ '!' '#' '{a,b}'
在某些地区无害但在其他地区危险的字符:
touch $'X\xa0Y' # non-breaking space in iso8859-1 which is considered
# "blank" and "space" in some locales
touch $'\xa3\x5c' $'\xa3\x60' # α and ε in BIG5 or BIG5-HKSCS charset, but
# �\ and �` in ASCII
在某些区域设置中排序相同的字符:
touch ① ② # sorts the same in GNU locales, order non-deterministic.
转义 glob 的文件.[!.]* *
(有时用于扩展隐藏和非隐藏文件):
touch ..foo ...