매개변수 목록을 텍스트 파일에서 bash 스크립트로 간접적으로 보낼 수 있나요?

매개변수 목록을 텍스트 파일에서 bash 스크립트로 간접적으로 보낼 수 있나요?

와일드카드를 포함하여 제가 하고 싶은 ls @files.lst몇 가지 일을 할 생각입니다 .ls [contents of files.lst]

나는 위의 구문(at-sign, 파일 이름)을 어딘가(아마도 마지막 빙하기 이전의 오래된 디지털 운영 체제?)에서 기억하고 있는 것 같습니다. Bash의 순열, 간접 참조, 매개 변수, 목록을 검색해도 아무런 도움이 되지 않았습니다. 나는 이것을 (모든?!) 스크립트에 작성하는 방법이 있다는 것을 알고 있지만 bash는 내가 지금까지 수행하지 않은 좀 더 일반적인 방식으로 이미 그것을 구현합니까?

업데이트: 이는 BSD/Darwin(ATM)에만 해당되지만 보다 일반적인 답변에도 감사드립니다. 저는 Mac을 사용하고 있는데, 지금쯤은 분명하지 않더라도 계산상의 비효율성이 다른 사람의 방해가 되지 않고 작업 부하도 최소화됩니다. 더 흥미로운 점은 기존 쉘 스크립트를 사용하여 명령줄에서 명령을 수신할 수 있다는 점입니다. 대부분의 경우 그렇게 됩니다.

답변1

텍스트 파일의 각 줄에서 일부 작업을 수행하려는 경우 일반적으로 두 가지 방법이 있습니다.

  1. 파일을 한 줄씩 읽고 루프 본문의 줄에서 수행해야 하는 작업을 수행합니다.

    while IFS= read -r pathname; do
        ls -d -- "$pathname"
    done <files.list
    

    위의 코드는 파일에서 줄을 읽고 files.listls -d --줄에서 실행됩니다.

    관련된:

  2. xargs또는 GNU 와 같이 루프를 암시적으로 만드는 유틸리티를 사용하십시오 parallel.

    xargs -I {} -- ls -d -- {} <files.list
    

    이 코드는 위 의 루프와 동일한 작업을 수행 xargs하지만 . 인수는 줄 바꿈이 이스케이프된 경우 삽입될 수 있는 줄입니다(따옴표도 처리되므로 그대로 유지하려면 이스케이프해야 합니다).ls -d --files.list

    xargs -- ls -d -- <files.list
    

    위의 코드는 ls -d --파일에서 가능한 한 많은 매개변수를 동시에 실행합니다. 포함된 탭이나 공백이 포함된 매개변수는 따옴표로 묶어야 하며 개별 포함된 줄 바꿈 및 따옴표는 이스케이프 처리되어야 합니다.

    GNU parallel유틸리티는 GNU 유틸리티보다 더 다양하며 xargs수행되는 작업을 더 잘 제어할 수 있습니다.

  3. 셸은 일반적으로 데이터 처리에 사용할 수 있는 가장 느린 언어이므로 파일의 각 줄에 대해 명령을 실행하는 것 외에 다른 작업을 수행해야 하는 경우 이를 더 쉽게 수행할 수 있는 언어를 사용하는 것이 좋습니다. 이것을하기 위해. 이러한 언어의 예:

    • 진주
    • 파이썬

두 경우 모두 파일에 줄 바꿈으로 구분된 경로 이름을 저장하므로 완전히 인용하지 않는 한 줄 바꿈이 포함된 경로 이름(Unix 시스템에서는 허용됨)을 사용할 수 없습니다 ( 매뉴얼 xargs참조 ).xargs

답변2

명령의 출력을 읽고 man xargs다음을 수행합니다.

xargs -r <files.lst somecommand

xargs명령줄은 필요한 만큼 실행하여 somecommand가능한 한 많은 항목으로 채워집니다 . 바라보다 .files.lstsomecommandxargs --show-limits </dev/null

xargs다음을 사용하여 한 번에 하나씩 파일 이름을 제공 할 수도 있습니다 .somecommand

xargs -r -n 1 <files.lst somecommand

답변3

Bash에 대해 자세히 알아보세요.www.tldp.org-> 배쉬 가이드

$ man bash몇 가지 세부 사항을 간략하게 설명합니다.

이제 대부분의 세부 정보가 포함된 위 소스를 우회하면
매우 간단하고 불완전한 답변을 얻을 수 있습니다.

$ ls -l $(cat file)
... 텍스트를 읽고 file인수에 삽입하여 lsLF(\n) 문자를 공백(SP) 문자로 바꿉니다.

여기서 트릭을 사용하지 않으면 와일드카드가 발생할 가능성이 낮습니다.

또 다른 문제에 유의하세요. 파일의 줄에 하나 이상의 공백이 포함되어 있으면 해당 줄의 단어가 됩니다 ls.

특정 명령(bash 관련 여부)이 파일에서 인수를 가져올 수 있는지 여부는 다양합니다.
man command_name일반적으로 지정된 명령의 세부 정보가 전달됩니다 command_name(실제 명령 이름으로 대체).

답변4

zsh쉘 에서 :

cmd -- $(<file)

기본값을 사용하면 $IFS공백/TAB/NL/NUL로 구분된 각 단어가 file( cmdksh에서) 후행 줄 바꿈 없이 확장되고 $(<file)인용되지 않은 경우 IFS 분할이 적용됩니다1)로 전달됩니다.file

cmd -- ${(f)"$(<file)"}

비어 있지 않은 각 줄의 내용은 별도의 인수로 전달됩니다 cmd( f인수 확장 플래그는 줄 바꿈으로 분할되고, f확장이 인용되지 않기 때문에 빈 인수는 삭제됩니다).

NL 대신 NUL로 분할하여 f대체 되었습니다 .0

cmd -- "${(Q@)${(zZ[n])$(<file)}}"

파일의 zsh 스타일 따옴표는 z따옴표 인식 토큰화를 위한 플래그와 함께 해석되고 사용되며, Z[n]줄 바꿈이 구분 기호로만 처리되도록 조정하고 Q따옴표를 제거하고 @따옴표와 함께 빈 요소를 유지합니다.

file예를 들어 비슷한 상황 에서는 다음과 같습니다 .

'' "foo bar"

whatever $'\n'

printf '<%s>\n'명령 으로 다음을 제공합니다.

$ printf '<%s>\n' $(<file)
<''>
<"foo>
<bar">
<whatever>
<$'\n'>
$ printf '<%s>\n' ${(f)"$(<file)"}
<'' "foo bar">
<whatever $'\n'>
$ printf '<%s>\n' "${(Q@)${(zZ[n])$(<file)}}"
<>
<foo bar>
<whatever>
<
>

1 Korn 쉘(또는 bash)에서는 IFS 분할의 영향을 받습니다.그리고와일드카드, 일반적으로 단어가 와일드카드 패턴을 의미하지 않는 한 이런 일이 발생하는 것을 원하지 않습니다. 또한 ksh/bash는 기본적으로 NUL로 분할되지 않습니다(그리고 일반적으로 이를 처리할 수 없습니다).

관련 정보