애플리케이션을 사용하여 파일 목록을 여는 프로세스 교체

애플리케이션을 사용하여 파일 목록을 여는 프로세스 교체

ls프로세스 대체를 사용하여 파일 목록(예: 또는 에서 생성됨 find)을 특정 응용 프로그램으로 열어서 보거나 보고 싶습니다 . 이러한 목록을 파이핑하는 것은 xargs스크립트나 바이너리에 대해 작동 하지만 xargs개체가 셸 별칭인 경우에는 실패합니다.이 사이트에 대한 기타 질문. [내가 염두에 두고 있는 구체적인 응용 프로그램은 다음과 같습니다 feh.]

xargsbash 별칭의 이러한 제한을 고려하여 대신 을 사용해 보았습니다 . [script/binary/alias] <(find . -iname '*')이 구성 은 모두 원하는 효과를 생성하지만 입력(파일 경로 목록)이 대신 열기/보기를 위해 애플리케이션(예: , . 프로세스 대체 문의 수신자가 되는 특정 경우 에 이 실패에 수반되는 오류는 " "입니다. 프로세스 대체 문 앞에 입력 리디렉션 연산자를 추가해도 문제가 완화되지 않습니다(예: 다른 명령의 경우와는 다름 ).catless<fehgimpfehfeh: No loadable images specified.less

따라서 내 질문은 명시된 목적(예: 파일 목록 열기)에 프로세스 대체를 사용할 수 있는지 여부와 그렇다면 적절한 구문이 무엇인지에 관한 것입니다. bash 별칭과의 호환성을 위한 특정 요구 사항( ~/.bash_aliases또는 유사한 구성 파일에 지정됨)

답변1

명령이 파이프를 통해 내용을 읽는 대신 여러 파일을 인수로 허용하는 경우 간단한 명령 대체가 작동합니다.

[script/binary/alias] $(find .)

또는 명령이 한 번에 하나의 파일만 허용하는 경우 for 루프가 트릭을 수행해야 합니다.

for file in $(find .); do [script/binary/alias] "$file"; done

두 경우 모두 공백, 탭, 줄 바꿈, 와일드카드가 포함된 파일 이름은 문제를 일으킬 수 있으며 while/read 루프는 이를 처리할 수 있습니다.

find . | while IFS= read -r file; do [script/binary/alias] "$file"; done

개행 문자가 포함된 파일 이름은 여전히 ​​문제를 일으킬 수 있습니다. find0으로 구분된 출력으로 문제가 해결됩니다(이 경우 bash, zsh, 로 가정 ksh).

find . -print0 | while IFS= read -rd '' file; do [script/binary/alias] "$file"; done

이러한 모든 예에서 find . -type f일반 파일만 처리하려는 경우 더 적절할 수 있습니다.

답변2

나중에 별칭을 확장하려면 xargs다음을 수행하세요.

alias xargs='xargs '

그러나 첫 번째 단어만 xargs별칭 확장의 영향을 받습니다. 이는 표준 명령에 대한 별칭이 있는 경우 의도하지 않은 영향을 미칠 수 있습니다.

$ alias xargs='xargs ' a='echo test'
$ set -x
$ echo x | xargs a
+ echo x
+ xargs echo test
test x
$ echo x | xargs -r a
+ echo x
+ xargs -r a
xargs: a: No such file or directory

별칭에 다른 이름을 지정하고 보다 합리적인 기본 동작을 사용할 수도 있습니다 xargs. GNU를 예로 들어보겠습니다 xargs.

alias axargs='xargs -r -d "\n" '

<(...)이제 프로세스 대체가 단일 매개변수, 즉 명령 출력(라이브 스트림)을 포함하는 파일 이름으로 확장됩니다.

출력의 경우 find이는 개행으로 구분된 파일 목록을 포함할 것으로 예상되는 파일 이름을 인수로 허용하는 명령에만 유용합니다.

feh중 하나이다:

feh -f <(find . -mtime -1 -type f -name '*.jpg')

이는 파일 이름에 개행 문자가 포함되지 않은 경우에만 작동합니다.

GNU 구현에는 파일 이름 목록을 안정적으로 전달할 수 있도록 ( or) 옵션과 결합된 파일에서 인수 목록을 가져오는 옵션이 xargs있습니다 .-a-0-print0-exec printf '%s\0' {} +find

xargs -r0a <(find ... -print0) feh....

하지만 이는 앨리어싱 문제를 해결하는 데 도움이 되지 않습니다.

이제 명령의 출력을 다른 명령의 인수로 전달하려면 다음을 사용할 수 있습니다.주문하다대신에 대체하다프로세스치환. 하지만 몇 가지 주의사항에 유의하시기 바랍니다.

cmdA "$(cmdB)"

후행 개행 문자 없이 의 출력을 cmdB인수로 전달합니다 cmdA. 예를 들어, 3개의 일반 파일(여기서는 특이하지만 완벽하게 유효한 이름) 이 있는 경우 * * /etc/passwd .jpg, foo.txt<nl><nl>( <nl>개행 문자를 나타냄) 의 출력 은 이므로 인수를 받습니다 .find . -type fcmdB./* * /etc/passwd .jpg<nl>./foo.txt<nl>./<nl><nl><nl>cmdA./* * /etc/passwd .jpg<nl>./foo.txt<nl>./

이것은 당신이 원하는 것이 아닐 수도 있습니다. cmdA각 파일 이름을 별도의 인수( ./* * /etc/passwd, ./foo.txt및 ) 로 받고 싶습니다 ./<nl><nl>.

따라서 기본적으로 출력을 별도의 파일 이름으로 분할해야 합니다 find. POSIX 쉘에는 하나의 연산자가 있습니다.분할+전역떠날 때 암시적으로 호출되는 연산자명령 대체(또는 매개변수 확장 또는 산술 확장) 따옴표 없이.

cmdA $(cmdB)

cmdB출력은 후행 줄 바꿈 없이 문자(기본값은 공백, 탭 및 줄 바꿈)로 분할되며 $IFS각 단어는 와일드카드로 표시됩니다.

위의 예에서는 이것이 우리가 원하는 것이 아닙니다. 이는 ./* * /etc/passwd .jpg, ./**으로 구분되며 현재 디렉터리의 파일 목록에 와일드카드로 /etc/passwd표시 됩니다 .jpg../**

우리가 원하는 것은 개행 문자로 분할하고 와일드카드 부분을 수행하지 않는 것입니다. 이는 다음을 통해 수행됩니다.

IFS='
' # newline only
set -f
cmdA $(cmdB)

개행 문자가 포함된 파일 이름에는 여전히 작동하지 않습니다. 개행 문자가 포함된 파일 이름이 없음을 사용하거나 보장할 수 없는 경우 일반적으로 의 출력은 find사후 처리가 불가능합니다 .-print0

이제 zsh분할 \0문자만 허용됩니다.

cmdA ${(0)"$(cmdB)"}

"$(cmdB)"분할은 NUL 문자 시퀀스를 기반으로 합니다 . 또는:

IFS=$'\0'  # no need for set -f in zsh
cmdA $(cmdB)

명령 대체 접근 방식의 또 다른 문제점은 cmdB실패하거나 아무것도 출력하지 않으면 cmdA인수 없이 계속 실행된다는 것입니다. 다음 구문을 사용하면 이를 방지하고 계속 사용할 수 있습니다 zsh.

cmdA ${$(find...):?no file}

하지만 사용하면 대부분의 기능이 내부적으로 지원되므로 zsh일반적으로 모든 문제를 해결할 필요가 없습니다 . 예를 들어 다음을 사용할 수 있습니다.zshfind

myalias ./**/*.jpg(.m-1)

jpg지난 24시간 동안 마지막으로 수정된 파일을 표시합니다 .

관련 정보