이건 후속작이야질문SO에 게시되었습니다.
except
나는 이와 같이 주어진 파일 이름/디렉토리를 제외한 모든 파일 이름/디렉토리를 인쇄해야 하는 스크립트를 작성했습니다 .
$ ls
a b c d
$ rm $(except b d)
$ ls
b d
지금까지 작성한 스크립트는 다음과 같습니다.
shopt -s extglob
shopt -s nullglob
old_ifs=$IFS
IFS='|'
matches="!($*)"
IFS=' '
printf '%s' $matches
IFS=$old_ifs
이것은 어느 정도 작동하지만 주요 문제는 printf가 (공백) IFS
설정을 존중하지 않는 것 같다는 것입니다 .
사이에 공백 없이 인쇄됩니다. 대신 echo를 사용하면 작동합니다(추가된 줄 바꿈 제외). 그러나 호환성상의 이유로 이 작업을 수행하려면 printf를 사용하고 싶습니다. 이 목표를 어떻게 달성할 수 있나요? 내가 뭘 잘못했나요?
또한 수정자를 사용해 보았 %q
으나 원하는 결과가 나오지 않았습니다.
printf '%q' $matches
답변1
$ ls a b c d $ rm $(except b d) $ ls b d
"except"
명령에 전달하기 전에 쉘이 출력을 분할(및 추가 확장)하는 방법을 결정할 방법이 없기 때문에 이것은 작동하지 않거나 적어도 신뢰할 수 없습니다 rm
.
귀하의 질문에 대답하기 위해 printf는 사용되지 않습니다 $IFS
. IFS를 사용하는 유일한 명령은 입니다 read
. 그 외에 쉘은 연결의 토큰화 및 위치 인수에 $IFS를 사용합니다 "$*"
.
다음을 수행할 수 있습니다.
printf '%s ' $matches
또는
printf '%s\n' $matches
하지만 다시,
rm $(except a b)
except
해당 명령줄을 해석하는 셸은 자체 상황에 따라 출력을 분할하고 $IFS
(기본값은 공백, 탭 또는 줄 바꿈이므로 공백 이상 을 사용해도 \n
차이가 없음) 와일드카드도 확장합니다.
a
따라서 and 이외의 파일이 b
and "this file.txt"
이면 **a**
출력 except
되고 and 를 "this file.txt **a** "
제거하려고 시도하게 됩니다 (해당 이름의 모든 파일로 확장되므로 ).this
file.txt
a
**a**
a
후행 공백 없이 공백과 일치 항목을 연결하려면 다음을 수행할 수 있습니다.
IFS=
set -- $matches
IFS=' '
matches="$*"