如何测试我的 shell 脚本的文件处理稳健性?

Jef*_*ler 12 shell-script error-handling

我已经编写了一个处理一些“常规”文件名的 shell 脚本,但我已经阅读了为什么我的 shell 脚本会因空格或其他特殊字符而阻塞?为什么你不应该分析LS的输出,我想它是更强大和处理任何有效的文件名(和/或目录名)。如何创建文件和目录的测试平台来运行我的脚本?

Jef*_*ler 12

创建一个单独的目录进行播放(主要是为了以后方便清理);这使用$TMPDIRif 设置的值,否则/tmp

mkdir "${TMPDIR-/tmp}/testing"
cd "${TMPDIR-/tmp}/testing"
Run Code Online (Sandbox Code Playgroud)

创建独立的文件,但由于空格(空格、制表符、换行符、回车、退格)而看起来彼此相似:

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
Run Code Online (Sandbox Code Playgroud)

以上归功于帕特里克。两个十六进制代码是 UTF-8 空格分隔符,称为nutmutton;“在双向上下文中,它充当空白并且(不是)镜像。在某些情况下,字形可能与其他 20 个字形混淆。”

创建一个普通文件,如果它被视为一个 glob,则会扩展到第一个文件:

touch -- x '[x]' 
Run Code Online (Sandbox Code Playgroud)

以上归功于 Wumpus Q. Wumbley

与此相类似:

touch -- 'a?b' 'a*b'
Run Code Online (Sandbox Code Playgroud)

在此处的评论中将上述内容归功于 dave_thompson_085

touch -- foo\`echo\ malicious\`bar
Run Code Online (Sandbox Code Playgroud)

以上归功于godlygeek

如果在 shell 上下文中评估,将扩展为不同的文件名(并且可能是任意执行!):

touch '$( echo boom )'
Run Code Online (Sandbox Code Playgroud)

用:

touch -- single\'quote double\"quote back\\slash
Run Code Online (Sandbox Code Playgroud)

捕获将文件名放在引号中而不转义引号的尝试。

touch -- -a -b -c -r -R - a=x
Run Code Online (Sandbox Code Playgroud)

以上归功于 Stéphane Chazelas

创建命名管道和符号链接(以创建非“常规”文件):

mkfifo fifo
ln -s a alink
Run Code Online (Sandbox Code Playgroud)

创建名称中包含各种空格的子目录,以及其中的令牌文件:

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
Run Code Online (Sandbox Code Playgroud)

创建仅包含*(删除可能有问题)的文件名、仅包含(常规!)空格的文件名、死符号链接、循环到自身的符号链接以及带有返回父目录的链接的子目录:

touch -- '*' '**' '***' ' '

ln -s /does/not/exist dead

ln -s loop loop

mkdir subdir_with_link
(cd subdir_with_link && ln -s .. parent)
Run Code Online (Sandbox Code Playgroud)

更多杂项文件名。最后两个是“分数斜线”和“除法斜线”的unicode。

touch -- '(' '!' '!!'  $'\xe2\x81\x84' $'\xe2\x88\x95'
Run Code Online (Sandbox Code Playgroud)

来自斯科特的想法:

touch -- '-' '--' ';' '&' '|' '<' '>' '$' ')' '{' '}' = \\ '!' '#' '{a,b}'
Run Code Online (Sandbox Code Playgroud)

在某些地方无害但在其他地方危险的字符:

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
Run Code Online (Sandbox Code Playgroud)

在某些语言环境中排序相同的字符:

touch ? ? # sorts the same in GNU locales, order non-deterministic.
Run Code Online (Sandbox Code Playgroud)

转义.[!.]* *glob 的文件(有时用于扩展隐藏和非隐藏文件):

touch ..foo ...
Run Code Online (Sandbox Code Playgroud)