다음은 Ishmael Smyrnow가 macOS 아이콘 캐시를 지우기 위해 작성한 한 줄짜리 bash 스크립트입니다.
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
나는 Ishmael의 버전에서 세미콜론이 줄 바꿈과 \;
문자 그대로의 세미콜론에 사용된다는 것을 알고 있습니다. 하지만 두 개의 세미콜론 사이와 별표 뒤에 공백을 두는 것이 무슨 소용이 있을까요? 삭제해도 안전합니까?
-exec rm -rfv {} \; ;
/Applications/* ;
답변1
쉘 언어 구문에서 공백을 언제 사용할지 여부는 사소한 문제가 아닙니다.
다양한 유형의 공간을 알아두는 것도 중요합니다.
공백과 탭은 구문에서 토큰을 구분하는 데 사용됩니다.
줄 바꿈은 토큰을 분리하지만 명령도 분리합니다. 예를 들어:
array=( foo bar baz )
(zsh의 구문은 이제 여러 다른 쉘에서 지원됩니다) 또는 ksh(C에서):
(( 1 + 2 ))
또는 POSIX sh(ksh에서도 올 수 있음):
var=$(( a + b ))
위의 공백, 탭 또는 줄 바꿈은 요소를 구분할 수 있습니다.
하지만:
cmd a cmd b
두 개의 별도 명령을 실행하십시오.
공백 대신 개행 문자를 사용할 수 있는 위치가 항상 명확한 것은 아니며 쉘마다 다를 수 있습니다.
일부 쉘(bash 포함)에서는 일부 다른 문자가 다음과 같이 분류됩니다.공백로케일에서 구문의 토큰 구분 기호로 사용될 수 있으며 줄 바꿈하지 않는 공백이 있는 U+00A0과 같은 문자를 포함할 수 있습니다(다음으로 분류되는 로케일에서만).공백)의 경우 바이트로 인코딩됩니다
bash
.
그런 다음 참조 연산자( "..."
, '...'
, $'...'
, $"..."
, \
)가 있는데, 이는 쉘 구문에서 문자가 갖는 특별한 의미를 제거하는 데 사용할 수 있습니다.
또한 단독으로 사용하거나 다른 문자와 결합하여 문법에서 단어를 구분하는 표시를 형성할 수 있는 여러 특수 문자(대부분 ();<>&|
어느 정도 `$
)도 있으므로 주위에 공백을 추가할 필요가 없습니다.
예를 들어 ksh에서는 다음과 같이 작성할 수 있습니다.
[[(a == b||d>c)&&0<1 ]]&&(echo yes)|cat
바꾸다:
[[ ( a == b || d > c ) && 0 < 1 ]] && ( echo yes ) | cat
왜냐하면 ||
, (
, &&
, <
, &&
...은 분리될 수 있는 단일 토큰이기 때문입니다.
Bash(최소 5.1)에서는 다음이 필요합니다.
[[(a == b||d>c)&&0 <1 ]]&&(echo yes)|cat
그렇지 않으면 일종의 오류가 발생한 것 같습니다.
$ bash -c '[[(a == b||d>c)&&0<1 ]]&&(echo yes)|cat'
bash: -c: line 1: unexpected token 284 in conditional command
bash: -c: line 1: syntax error near `&0<'
bash: -c: line 1: `[[(a == b||d>c)&&0<1 ]]&&(echo yes)|cat'
(아마도 Outside of [[...]]
, in cmd 0<file
, 0<
in 자체가 연산자이므로 별도의 토큰으로 처리될 가능성이 높기 때문일 것입니다.)
존재하다:
foo \;;bar
모호함은 없습니다. 단어 foo
, 구분 기호로 처리되는 공백, 따옴표 ;
( \;
여기와 동일), 토큰 및 then 입니다. 따라서 다음과 같은 방식으로 처리됩니다.';'
";"
;
bar
foo ';' ; bar
공백을 추가해도 해가 되지 않으며 가독성을 높이는 데 도움이 됩니다.
이 코드는 다음과 같이 작성(및 개선)할 수도 있습니다.
sudo zsh -c '
rm -rfv /Library/Caches/com.apple.iconservices.store
find /private/var/folders/ \
"("
-name com.apple.dock.iconcache -o \
-name com.apple.iconservices \
")" -prune -exec rm -rfv {} +
sleep 3
touch /Applications/*'
killall Dock
killall Finder
당신이 알아차릴 것:
sudo
한 번만 실행하고 여러 줄로 묶인 인용 문자열을 별도의 zsh 호출에 대한 인수로 전달하면 모든 문자가 셸에 대한 특별한 의미를 잃습니다.\
개행 다음에 오는 것은 위에 언급되지 않은 또 다른 특별한 경우입니다. 이렇게 하면 개행 문자가 사라집니다(내부 셸의 경우, 외부 셸의 경우 백슬래시와 개행 문자는 작은따옴표 안에 있으므로 리터럴로 유지됩니다).- 우리는 한 명만 전화해요
find
- 우리는 실행될 명령을 구성하는 인수 목록을 분리
+
하지 않기 위해( 셸이 아닌) 사용하므로 각 디렉터리에 대해 한 번이 아니라 제거할 모든 디렉터리에 대해 한 번 호출합니다.;
find
-exec
rm
-prune
so를 사용하면 삭제할 디렉토리find
에 들어가려고 시도하지 않습니다 .rm
- 나는 더 명확하다고 생각하기 때문에
"("
대신 사용하고 있습니다 .\(
보통은 여기를 사용하는데'('
, 모든 것이 안에 있어서'...'
사용할 수 없습니다. - glob이 일치하지 않을 때 문자 그대로 전달되는 버그 기능이 있기 때문에
zsh -c
대신 사용합니다 . 따라서 에 숨겨지지 않은 파일이 없으면 in이라는 이름의 파일이 생성됩니다 . zsh에서는 일치하는 항목이 없으면 오류가 발생합니다.sh -c
sh
sh
touch /Applications/*
*
/Applications