以Bash相同的方式转义文件名



当我在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

最新更新