我的主文件夹中有两个名为“'?”的文件。和“'?;?” (没有双引号)。我该如何删除它们?我试图使用转义,但它不起作用。
答案 0 :(得分:4)
使用单引号或双引号来避免通配符扩展。 ?
是一个通配符,表示shell与任何一个单个字符匹配。通过将其放在引号中,您告诉shell不要执行通配符扩展。
rm '?' '?;?'
rm "?" "?;?"
这将删除名为“?”的两个文件和“?;?”
你也可以使用反斜杠来引用对shell有特殊意义的单个字符,这样你就可以这样做
rm \? \?\;\?
注意你必须引用'?'防止路径名扩展,你必须引用';'因此shell不会将其解释为分离命令。
如果省略引号,那么shell会以不同方式解析它。这是我跑过的一个实验。
$ for i in {1..4}; do for j in {a..c}; do touch "$i;$j" $j '?' '?;?';done;done
$ ls
1;a 1;b 1;c 2;a 2;b 2;c 3;a 3;b 3;c 4;a 4;b 4;c ? ?;? a b c
$ rm ? ?;?
rm: cannot remove `?': No such file or directory
rm: cannot remove `a': No such file or directory
rm: cannot remove `b': No such file or directory
rm: cannot remove `c': No such file or directory
bash: ?: command not found
$ rm `echo "?" "?;?"`
rm: cannot remove `?': No such file or directory
$
这里发生的事情是shell做了路径名扩展,所以
rm ? ?;?
成了
rm ? a b c ? a b c;? a b c
rm
命令删除了文件a b c?然后抱怨找不到以下文件(它们已被删除)。分号分隔命令,然后尝试调用'?'命令传递参数“a”“b”“c”......但是没有'?' command - 名为'?'的文件刚刚被删除,无论如何它都不可执行 - 所以shell抱怨“?”找不到命令。
如果要删除所有匹配“?”的文件和“?;?”你需要欺骗shell扩展那些,我喜欢这样做
rm `echo "?" "?;?"`
这是由shell分两步扩展的,首先它运行echo "?" "?;?"
,这导致两个字符串,“?”和“?;?”,然后它使用这些字符串进行路径名扩展,以生成rm
的参数,从而产生
rm ? 1;a 1;b 1;c 2;a 2;b 2;c 3;a 3;b 3;c 4;a 4;b 4;c ?;?
请注意'?'的通配符扩展这次没有产生任何匹配的文件(它们之前已被删除),所以shell传递'?'作为rm
的参数,成功删除作为参数传递的所有文件,除了'?'所以它抱怨这个。
这是另一个实验
$ for i in {1..4}; do for j in {a..c}; do touch "$i;$j" $j '?' '?;?';done;done
$ ls
1;a 1;b 1;c 2;a 2;b 2;c 3;a 3;b 3;c 4;a 4;b 4;c ? ?;? a b c
$ rm "?" "?;?"
$ ls
1;a 1;b 1;c 2;a 2;b 2;c 3;a 3;b 3;c 4;a 4;b 4;c a b c
$ rm `echo "?" "?;?"`
$ ls
$
有关更多信息,请参阅globbing的手册页
man 7 glob
通配符匹配 字符串是通配符模式,如果它包含字符'?','*'或'[')之一。 Globbing就是这样的操作 将通配符模式扩展到与模式匹配的路径名列表中。匹配定义如下:
A '?' (not between brackets) matches any single character.
A '*' (not between brackets) matches any string, including the empty string.
答案 1 :(得分:2)
请注意,ls
可以为任意不可打印的字符报告问号,因此您作为文件名获得的内容可能不包含问号。
您可以使用ls -b
命令或ls | cat
来发现此信息。
作为一个复杂的例子,完成补救措施,我创建了一个像这样的脚本convolvulus
:
set -x
mkdir convoluted &&
(
cd convoluted
cp /dev/null "$(ls -la | sed 1d)"
ls
ls -b
ls | cat
ls -la | cat
cp /dev/null $'\n'
cp /dev/null $'\n;\n'
ls -als | cat
ls -lab
ls
ls | cat
rm $'\n' $'\n;\n' d*
ls -a
)
rm -fr convoluted
跑步时,它产生了:
$ bash convolvulus 2>&1 | so
+ mkdir convoluted
+ cd convoluted
++ ls -la
++ sed 1d
+ cp /dev/null 'drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..'
+ ls
drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ ls -b
drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .\ndrwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ ls
+ cat
drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ ls -la
+ cat
total 0
drwxr-xr-x 3 jleffler staff 102 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
-rw-r--r-- 1 jleffler staff 0 Mar 9 11:58 drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ cp /dev/null '
'
+ cp /dev/null '
;
'
+ ls -als
+ cat
total 0
0 -rw-r--r-- 1 jleffler staff 0 Mar 9 11:58
0 -rw-r--r-- 1 jleffler staff 0 Mar 9 11:58
;
0 drwxr-xr-x 5 jleffler staff 170 Mar 9 11:58 .
0 drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
0 -rw-r--r-- 1 jleffler staff 0 Mar 9 11:58 drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ ls -lab
total 0
-rw-r--r-- 1 jleffler staff 0 Mar 9 11:58 \n
-rw-r--r-- 1 jleffler staff 0 Mar 9 11:58 \n;\n
drwxr-xr-x 5 jleffler staff 170 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
-rw-r--r-- 1 jleffler staff 0 Mar 9 11:58 drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .\ndrwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ ls
;
drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ ls
+ cat
;
drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ rm '
' '
;
' 'drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..'
+ ls -a
.
..
+ rm -fr convoluted
$
玩得开心!
-b
的{{1}}选项适用于GNU ls
以及适用于Mac OS X和BSD ls
(但未由POSIX定义)。
ls
表示法是Bash ANSI-C Quoting。
答案 2 :(得分:1)
在文件名周围使用引号:
$ ls
? ?;?
$ rm '?'
$ ls
?;?
$ rm "?;?"
$ ls
$