먼저 사소하지만 적용할 수 없는 답변을 잘라냅니다. 호출당 이러한 표현식을 거의 사용해야 하기 때문에 find
+ xargs
트릭이나 그 변형(예: find
with )을 사용할 수 없습니다 . -exec
마지막에 이 주제로 다시 돌아오겠습니다.
이제 더 나은 예를 들어 다음을 고려해 보겠습니다.
$ find -L some/dir -name \*.abc | sort
some/dir/1.abc
some/dir/2.abc
some/dir/a space.abc
매개변수로 어떻게 전달하나요 program
?
이렇게만 하면 문제가 해결되지 않습니다
$ ./program $(find -L some/dir -name \*.abc | sort)
program
다음 매개변수를 얻었 기 때문에 실패했습니다 .
[0]: ./program
[1]: some/dir/1.abc
[2]: some/dir/2.abc
[3]: some/dir/a
[4]: space.abc
볼 수 있듯이 공백이 있는 경로는 분할되어 program
두 개의 다른 매개변수로 처리됩니다.
유효일까지 견적
저와 같은 초보 사용자는 이러한 문제에 직면했을 때 마침내 작동할 때까지 무작위로 인용문을 추가하는 경향이 있는 것 같습니다. 여기서는 도움이 되지 않는 것 같습니다...
"$(…)"
$ ./program "$(find -L some/dir -name \*.abc | sort)"
[0]: ./program
[1]: some/dir/1.abc
some/dir/2.abc
some/dir/a space.abc
따옴표는 단어 분리를 방지하므로 모든 파일은 단일 인수로 전달됩니다.
별도의 경로 참조
유망한 접근 방식:
$ ./program $(find -L some/dir -name \*.abc -printf '"%p"\n' | sort)
[1]: "some/dir/1.abc"
[2]: "some/dir/2.abc"
[3]: "some/dir/a
[4]: space.abc"
물론 인용문도 있습니다. 그러나 더 이상 설명되지 않습니다. 그것들은 단지 문자열의 일부일 뿐입니다. 그래서 그들은 분사를 멈추지 않았을 뿐만 아니라 논쟁도 벌였습니다!
IFS 변경
그런 다음 나는 놀아 보았습니다 IFS
. 어쨌든 나는 "유선 경로"자체에서 문제를 일으키지 않도록 find
with -print0
및 sort
with - 를 선호합니다. 그렇다면 역할 분할을 강제하여 모든 것을 갖추는 것은 -z
어떨까요 ?null
$ ./program $(IFS=$'\0' find -L some/dir -name \*.abc -print0 | sort -z)
[0]: ./program
[1]: some/dir/1.abcsome/dir/2.abcsome/dir/a
[2]: space.abc
따라서 여전히 공간적으로 분할되어 있고 수직으로 분할되지는 않습니다 null
.
나는 (위와 같이) IFS
before와 before에 과제를 넣어 보았습니다 . 나는 또한 with , with ,without과 같은 다른 구문을 시도했습니다 . 이들 중 어느 것도 아무런 차이가 없는 것 같습니다.$(…)
./program
\0
\x0
\x00
'
"
$
이제 아이디어가 없어졌습니다. 몇 가지를 더 시도했지만 모두 동일한 문제가 나열된 것 같습니다.
내가 또 무엇을 할 수 있나요? 이것이 가능한가?
물론 program
수락 모드를 만들어 직접 검색할 수도 있습니다. 하지만 이를 특정 구문으로 수정하는 동안 많은 이중 작업이 필요합니다. ( grep
예를 들어 a를 통해 파일을 제공하는 것은 어떻습니까?)
program
또한 경로 목록이 포함된 파일을 허용 하도록 만들 수도 있습니다 . 그런 다음 find
표현식을 임시 파일에 쉽게 덤프하고 해당 파일에 대한 경로를 제공할 수 있습니다 . 이는 사용자가 단순 경로만 가지고 있는 경우 중간 파일 없이 제공될 수 있도록 직접 경로를 따르는 것을 지원할 수 있습니다. 그러나 이는 보기에 좋지 않습니다. 추가 구현이 필요한 것은 말할 것도 없고 추가 파일을 생성하고 처리해야 합니다. (그러나 장점으로는 인수인 파일 수가 명령줄 길이 문제를 일으키기 시작하는 경우 도움이 될 수 있습니다...)
마지막으로, 내 경우에는 find
+ (및 유사한) 트릭이 작동하지 않았다는 점을 다시 한번 상기시켜 드리겠습니다 . xargs
설명을 단순하게 유지하기 위해 하나의 매개변수만 표시합니다. 하지만 내 실제 사례는 다음과 같습니다.
$ ABC_FILES=$(find -L some/dir -name \*.abc | sort)
$ XYZ_FILES=$(find -L other/dir -name \*.xyz | sort)
$ ./program --abc-files $ABC_FILES --xyz-files $XYZ_FILES
그래서 하나를 검색해 xargs
도 다른 하나는 어떻게 해야 할지 궁금합니다...
답변1
배열을 사용하세요.
파일 이름에 줄 바꿈 가능성을 처리할 필요가 없다면 이스케이프할 수 있습니다.
mapfile -t ABC_FILES < <(find -L some/dir -name \*.abc | sort)
mapfile -t XYZ_FILES < <(find -L other/dir -name \*.xyz | sort)
그 다음에
./program --abc-files "${ABC_FILES[@]}" --xyz-files "${XYZ_FILES[@]}"
만약 너라면하다파일 이름의 줄 바꿈을 처리해야 하고 bash >= 4.4인 경우 배열 구성 중에 이름을 null로 종료하는 데 -print0
및를 사용할 수 있습니다.-d ''
mapfile -td '' ABC_FILES < <(find -L some/dir -name \*.abc -print0 | sort -z)
(그것도 비슷합니다 XYZ_FILES
). 만약 너라면아니요최신 bash를 사용하면 null로 끝나는 읽기 루프를 사용하여 파일 이름을 배열에 추가할 수 있습니다.
ABC_FILES=()
while IFS= read -rd '' f; do ABC_FILES+=( "$f" ); done < <(find -L some/dir -name \*.abc -print0 | sort -z)
답변2
IFS=newline을 사용할 수 있지만(파일 이름에 개행 문자가 포함되어 있지 않다고 가정) 교체하기 전에 셸에서 이를 설정해야 합니다.
$ ls -1
a file with spaces
able
alpha
baker
boo hoo hoo
bravo
$ # note semicolon here; it's not enough to be in the environment passed
$ # to printf, it must be in the environment OF THE SHELL WHILE PARSING
$ IFS=$'\n'; printf '%s\n' --afiles $(find . -name 'a*') --bfiles $(find . -name 'b*')
--afiles
./able
./a file with spaces
./alpha
--bfiles
./bravo
./boo hoo hoo
./baker
null을 사용 zsh
하지만 사용하지 않는 것도 bash
가능합니다. 개행 문자를 처리할 수 $'\0'
있다고 해도 bash
이렇게 한 번도 사용되지 않은 이상한 문자가 있다면
IFS=$'\1'; ... $(find ... -print0 | tr '\0' '\1') ...
그러나 이 방법은 @steeldriver의 답변에 대한 의견에서 작성한 추가 요청, 즉 find a가 비어 있는 경우 --afiles를 생략하는 추가 요청을 처리할 수 없습니다.
답변3
왜 포기했는지 잘 모르겠습니다 xargs
.
그래서 하나를 검색해
xargs
도 다른 하나는 어떻게 해야 할지 궁금합니다...
문자열은 --xyz-files
많은 매개변수 중 하나일 뿐이며 프로그램이 해석할 때까지 그것이 특별하다고 생각할 이유가 없습니다. 두 가지 결과 xargs
모두 find
에서 이를 전달할 수 있다고 생각합니다 .
{ find -L some/dir -name \*.abc -print0 | sort -z; echo -ne "--xyz-files\0"; find -L other/dir -name \*.xyz -print0 | sort -z; } | xargs -0 ./program --abc-files