当我在bash
中使用"tab"键时(当您已经开始键入文件名并希望它完成时(,bash
会正确地转义文件名,如果我使用的是"转义"的文件名,它就会起作用。
例如:
An-Beat - Mentally Insine (Original Mix).mp3
=>bash
使用"TAB"逃离后An-Beat - Mentally Insine (Original Mix).mp3
我正在为bash
搜索一个函数,该函数将以"tab"转义文件名的方式转义文件名。
使用printf
(1(:
x='a real good %* load of c$rap'
x=$(printf '%q' "$x")
echo $x
将返回
a real \good %* load of c$rap
我将详细说明他对此的回应。
如果要将要转换为shell脚本参数的参数传递,请将该参数封装在"中。
#!/bin/bash
x=$(printf '%q' "$1")
echo $x
我真的很喜欢printf解决方案,因为它处理每一个特殊的字符,就像bash一样。
$ string="An-Beat - Mentally Insine (Original Mix).mp3"
$ echo ${string// /\ }
An-Beat - Mentally Insine (Original Mix).mp3
$ string=${string// /\ }
$ echo ${string//(/\( }
An-Beat - Mentally Insine ( Original Mix).mp3
来自"sehe"的解决方案运行良好,此外,您还可以使用双引号("(而不是单撇号('(来使用变量:
x="a real good %* load of crap from ${USER}"
echo $(printf '%q' "$x")
当然,字符串可能不包含$或"本身,或者您必须手动通过splash\$.
ls --quoting-style=escape /somedir
这将输出转义的文件名,也适用于unicode字符,printf方法不适用于中文,它输出类似$'\206\305…'的
我可能会迟到一点,但对我有用的是:
ls --quoting-style=shell-escape
通过这种方式,它还可以转义像!
或'
这样的字符。
我正在为bash搜索一个函数,该函数将以相同的方式转义文件名";选项卡";转义文件名。
获取转义完整路径的解决方案
我创建了一个可移植的函数来获取当前目录中所有项目的所有转义路径,并在macOS和Linux上进行了测试(需要安装GNUbash(。
escpaths() {
find "$PWD" -maxdepth 1 -print0 | xargs -0 -I {} bash -c 'printf "%qn" "$0"' {} | sort
}
下面是一个严格的测试用例场景:
# Generate test directory, containing test directories and files.
mkdir 'test dir'; cd 'test dir'
mkdir 'dir with backslashes\'
touch 'file with \backslashes'
touch 'An-Beat - Mentally Insine (Original Mix).mp3'
mkdir 'crazy(*@$):{}[]dir:'
mkdir 'dir with 字 chinese 鳥鸟 characters'
touch $'filetwithtmanyttabs.txt'
touch 'file @*&$()!#[]:.txt'
touch 'file
with
newlines.txt'
在测试目录test dir
中执行escpaths
会给出转义输出:
$'/.../test dir/filenwithnnewlines.txt'
$'/.../test dir/filetwithtmanyttabs.txt'
/.../test dir
/.../test dir/An-Beat - Mentally Insine (Original Mix).mp3
/.../test dir/\dir with\ backslashes\\\
/.../test dir/\file with \\backslashes\
/.../test dir/crazy(*@$):{}[]dir:
/.../test dir/dir with 字 chinese 鳥鸟 characters
/.../test dir/file @*&$()!#[]:.txt
仅获取转义基名称的解决方案
这个(也是可移植的(函数将为您获取当前目录中所有项的转义基名称(这次不包括当前目录(。
escbasenames() {
find . -mindepth 1 -maxdepth 1 -exec printf '%s ' "$(basename {})" ; | xargs -0 -I {} bash -c 'printf "%qn" "${0#./}"' {} | sort
}
在同一测试目录test dir
中运行escbasenames
会得到转义的基名称:
$'filenwithnnewlines.txt'
$'filetwithtmanyttabs.txt'
An-Beat - Mentally Insine (Original Mix).mp3
\dir with\ backslashes\\\
\file with \\backslashes\
crazy(*@$):{}[]dir:
dir with 字 chinese 鳥鸟 characters
file @*&$()!#[]:.txt
尾注
请注意,如果路径/文件名包含换行符或制表符,它将被编码为ANSI-C字符串。终端中的自动完成也使用ANSI-C字符串完成。示例ANSI-C字符串自动补全输出看起来像my$'n'newline$'n'dir/
或my$'t'tabbed$'t'file.txt
。