这是 Ishmael Smyrnow 编写的一行 bash 脚本,用于清除 macOS 图标缓存:
sudo rm -rfv /Library/Caches/com.apple.iconservices.store; sudo find /private/var/folders/ \( -name com.apple.dock.iconcache -or -name com.apple.iconservices \) -exec rm -rfv {} \; ; sleep 3;sudo touch /Applications/* ; killall Dock; killall Finder
我尝试了解如何将其改回多行版本。这是我现在所拥有的:
sudo rm -rfv /Library/Caches/com.apple.iconservices.store
sudo find /private/var/folders/ -name com.apple.dock.iconcache -exec rm -rfv {} \;
sudo find /private/var/folders/ -name com.apple.iconservices -exec rm -rfv {} \;
sleep 3
sudo touch /Applications/*
killall Dock
killall Finder
我确实理解以实玛利的版本分号用于换行符和\;
文字分号。但是两个分号之间和星号后面有一个空格的目的是什么?删除它们安全吗?
-exec rm -rfv {} \; ;
/Applications/* ;
在 shell 语言语法中何时使用或不使用空格并不是一件小事。
同样重要的是要注意不同类型的空间:
空格和制表符用于分隔语法中的标记
换行符分隔标记,但也分隔命令。例如:
(来自 zsh 的语法现在已被其他几个 shell 支持)或 ksh 的(来自 C):
或者 POSIX sh(也可以来自 ksh):
上面的空格、制表符或换行符可以分隔元素。
但:
运行两个单独的命令。
哪里可以使用换行符代替空格并不总是很清楚,并且在 shell 之间可能有所不同。
在某些 shell(包括 bash)中,在区域设置中被分类为空白的其他一些字符可以用作语法中的标记分隔符,并且可以包括诸如 U+00A0 之类的字符:不间断空格(仅在被分类为空白的区域设置中)在 ) 的情况下编码为一个字节
bash
。然后是引用运算符 (
"..."
,'...'
,$'...'
,$"..."
,\
),它们可用于删除字符在 shell 语法中具有的任何特殊含义。还有许多特殊字符(主要
();<>&|
是在某种程度上`$
),它们可以单独使用,也可以与其他字符组合形成语法中的标记,这些标记也可以分隔单词,因此不需要在它们周围添加空格。例如,在 ksh 中,您可以编写:
代替:
因为
||
,(
,&&
,<
,&&
... 是可以分隔的单个标记。在 bash(至少 5.1)中,你会发现你需要:
否则你似乎遇到了某种错误:
(可能是因为 Outside of
[[...]]
、 incmd 0<file
、0<
in 本身就是一个运算符,因此很可能被视为单独的标记)。在:
没有歧义,这是一个
foo
单词、被视为分隔符的空格、一个引号;
(与此处\;
相同)以及标记和 then 。因此它的处理方式与:';'
";"
;
bar
添加空格不会造成损害,而且有助于提高可读性。
该代码也可以编写(并改进为):
你会注意到的地方:
sudo
仅运行一次,并将多行带引号的字符串作为参数传递给单独的 zsh 调用,其中所有字符都失去了对外壳的特殊含义。\
后面跟着换行符是上面没有提到的另一种特殊情况。这使得换行符消失(对于内壳;对于外壳,反斜杠和换行符位于单引号内,因此保持原义)。find
+
not 来;
分隔(对于find
,而不是 shell)组成执行命令的参数列表-exec
,因此rm
对要删除的所有目录调用一次,而不是对每个目录调用一次。-prune
sofind
不会尝试进入rm
要删除的目录。"("
代替,\(
因为我发现它更清晰。通常我会使用'('
behere,整个东西都在里面'...'
,所以我们不能使用它。zsh -c
而不是sh -c
因为sh
有一个错误特征,即当 glob 不匹配时,它们会按字面意思传递,因此 insh
,如果那里没有非隐藏文件,将创建一个名为in的touch /Applications/*
文件。在 zsh 中,如果没有匹配项,则会出现错误。*
/Applications