.system()
find
다음과 같이 파일 목록을 가져오고 스크립트를 실행하고 싶습니다 .
find <arguments> -printf "%f\n" | script.awk
문제는 이러한 파일에 공백, 따옴표, 괄호와 같은 특수 문자가 포함되어 있다는 것입니다. 예를 들어:
$ ls
'Aujourd'\''hui C'\''est Toi (Orchestral).flac'
나는 다음과 같은 모든 종류의 인용문을 시도했습니다.
system("<command> \""$0"\"")
이:
system("<command> \'"$0"\'")
온갖 종류의 오류가 발생합니다. 이러한 오류 중 일부는 다음에서 발생했으며 sh -c
일부는 gawk
... 에서 발생했습니다.
$0
이러한 모든 문제가 발생하지 않고 gawk 스크립트의 레코드나 기타 변수를 쉘 명령으로 전달할 수 있는 방법이 있습니까 ?
메모:일시적으로 파일 이름을 바꾸는 것이 더 쉬울 수 있다는 것을 알고 있지만 이를 피하는 것이 더 어렵다는 것을 알았습니다.
편집하다:
제안된 답변 중 어느 것도 내 문제를 해결하지 못했으므로 여기에 문제에 대한 보다 구체적인 설명이 있습니다. 다음을 사용하는 명령을 실행하려고 합니다.2이상한 변수. 예:
내가 실행하면 :
system("metaflac --show-tag=ARTIST \""FILE"\"")
인용했기 때문에 오류가 발생하지 FILE
않고 큰따옴표가 포함되어 있지 않기 때문에 괜찮습니다.
하지만 내가 실행하면 :
system("metaflac --set-tag=ARTIST="AWK_VAR_WITH_ARTIST_VALUE" "\"FILE\")
인용을 해도 metaflac
flac 파일을 찾을 수 없다고 오류가 뜹니다. 오류 메시지를 읽어보니 파일 이름이 여러 단어로 나뉘어져 있는 것을 볼 수 있습니다.
답변1
system("<command> \"$0\"")
awk의 프로세스에 쓰기 기능으로 대체할 수 있습니다 print $0 | "pre;<command> \"$v\""
.미리부분은 stdin을 쉘 변수 v로 읽습니다. bash에서는 이것은 read -r v
. 예를 들면 다음과 같습니다.
awk 'BEGIN{ cmd="read -r v; ls -ld \"$v\"" }
{ print $0 | cmd; close(cmd); }'
파일 이름의 개행과 같은 끔찍한 일을 처리하려면 find에서 print0 경로로 이동할 수 있으며, awk가 허용하는 경우 RS='\0'
bash를 사용할 수 있습니다.
find . -print0 |
awk -v RS='\0' '
BEGIN{ cmd="read -r -d \"\" v; ls -ld \"$v\"" }
{ print $0 "\x00" | cmd; close(cmd); }'
답변2
공백과 작은따옴표의 특정 경우에는 문자열을 큰따옴표로 묶는 것으로 충분합니다.
$ find -name 'Aujour*' -printf "%f\n" | awk '{system("ls -l \""$0"\"")}'
-rw-rw-r-- 1 user user 0 May 26 11:27 Aujourd'hui C'est Toi (Orchestral).flac
find
또는 쉘이 쉘 인용 형식 지정자를 제공하는 경우 '의 내부 대신 이를 사용하는 것을 고려할 수 있습니다 -printf
.
$ find -name 'Aujour*' -exec printf '%q\n' {} \; | awk '{system("ls -l "$0)}'
-rw-rw-r-- 1 user user 0 May 26 11:27 ./Aujourd'hui C'est Toi (Orchestral).flac
help printf
예 를 들어 다음 bash
과 같습니다.
%q quote the argument in a way that can be reused as shell input