2017-04-13 7 views
1

파일에서 ll 명령의 인수를 읽으려고합니다. 파일 args.txt의 내용이 some?입니다. 나는 some1, some2some3이라는 이름의 파일과 다른 파일들이 있습니다. cat args.txt | ll을 실행할 때 ll을 실행할 때와 같은 결과를 얻습니다.파일에서 glob로 인수 목록 읽기

누군가가 왜 그런지 설명하고 원하는 결과를 얻을 수 있습니까? 미리 감사드립니다.

+1

@DPM, BTW,'ll'은 실제로 존재하는 유닉스 명령이 아닙니다. * 여러 시스템에서 바로 사용할 수있는 별칭 *이지만 별칭은 실제 명령이 아닙니다. 명령을 해석하기 전에 접두사를 다른 문자열로 바꾸라는 명령 일뿐입니다. 쉘이 아닌 프로그램 (그리고'xargs'는 그러한 프로그램입니다)은 별칭을 인식하지 못하기 때문에 실행할 수 없습니다. –

답변

5

참고 : 나는 llls -l 또는 일부 변화에 대한 별명이라고 가정하고있다.
Charles Duffy가 지적했듯이 (기본값) 대화 형 셸은 별칭을 알기 때문에 스크립트뿐만 아니라 xargs 같은 도구는 알지 못합니다. 당신이 명령에 파이프 라인을 통해 전송 무엇

은 명령의 인수 (예 : -lsome? 같은 피연산자 옵션)과 구별되는 그 표준 입력 스트림을 통해 수신된다.

따라서, 명시 적 변환은 당신이 통과 할 수있는 인수에 파일 args.txt의 내용을 변환 할 필요가 ls -l에 : 명령 대체 ($(...))이 의도적으로 인용되지 않은 것을

ls -l $(cat args.txt) # In Bash you can simplify to: ls -l $(< args.txt) 

이되도록 glob(파일명 확장)을 원하는대로 args.txt의 내용에 적용합니다.

취성 인이 기술은 드물지만 실제로는 이 필요합니다.입니다.

취성을 설명하려면 : 예를 들어 globbing 패턴이 "some file"? 인 경우 (두 개의 따옴표를 사용하여 패턴을 단일 인수로 인식해야하는 경우),이 명령은 더 이상 작동하지 않습니다. " 문자는 명령 대체 (또는 변수 확장)의 결과 일 때 구문 기능을 잃습니다.


인수에 표준 입력이나 파일 내용을 변환하는 표준 유틸리티 xargs입니다. 파일이 포함되어 있기 때문에, 은 특정 경우에 그것은 하지 옵션글로브에 의해 확장 될 수 있지만 xargs는 쉘을 포함하지 않고, 외부 유틸리티를 호출합니다 (파일 이름 패턴) :

$ xargs ls -l < args.txt # !! Does NOT work as intended here. 
ls: file?: No such file or directory 

파일 이름 file?그대로ls에 전달했다 (실제로 file?를라는 이름의 파일이 존재하지 않음) - 아무 쉘이 포함되지 않았기 때문에 어떤 대체 (globbing)은 일어나지 않았다. 다음

0

당신은 (귀하의 경우 ll를) 명령에 고양이의 출력을 전달하는 xargs를 사용할 수 있습니다

cat args.txt | xargs ll 

당신의 args.txt이 새로운 라인 또는 공백으로 구분하여 여러 값을 포함하는 경우, xargs을 전달합니다 각 값에 별도로, 당신의 args.txt 항목으로, 여러 번 명령을 실행 : 예를 들어

, 당신의 args.txt이 콘텐츠가있는 경우 :

/var/ 
/usr/ 
/usr /var 
을 실행 0

그리고 그 결과는 다음과 같이 표시됩니다

$ cat args.txt | xargs ls 
/usr: 
bin etc games include lib lib64 libexec local sbin share src tmp 

/usr/: 
bin etc games include lib lib64 libexec local sbin share src tmp 

/var: 
adm cache crash cvs db empty games gopher kerberos lib local lock log mail nis opt preserve run spool tmp var yp 

/var/: 
adm cache crash cvs db empty games gopher kerberos lib local lock log mail nis opt preserve run spool tmp var yp 
+0

기본적으로'xargs'는 한 줄에 편리하게 맞는 많은 인수를 모으므로 입력에있는 항목보다 훨씬 적은 시간에 명령을 실행합니다. 인수 당 하나의 명령을 강제 실행하는 방법이 있습니다. 이것은 또한 파일 이름에 공백이있는 파울을 실행합니다. –

+1

'll'이 별명이면,'xargs ll'은 작동하지 않을 것입니다. –

3

다소 과잉이지만,에 관계없이 쉘 구성의 정확하고 일관성이 있어야하고, (심지어 공백을하는) 모든 가능한 파일 이름과 함께 작업 할 고통에 간다 :

# note f() () instead of f() { }; this runs in a subshell, so its changes to IFS or 
# shopt settings don't modify behavior of the larger shell. 
globfiles() (
    set +f      ## ensure that globbing is enabled 
    shopt -u nullglob failglob ## ensure that non-default options on how to handle failed 
           ## ...glob attempts are both disabled 
    IFS=      ## disable string-splitting 
    while IFS= read -r -d '' filename; do 
    printf '%s\0' $filename ## unquoted use -> expand as glob 
           ## ...expands format string once per argument, hence once per 
           ## ...file found. (No string-splitting due to prior IFS=) 
    done 
) 

... 그 이후 사용 (당신의 입력 파일은 줄 바꿈으로 구분 된 경우)로 :

tr '\n' '\0' <args.txt | globfiles | xargs -0 ls -l -- 

... 또는 (사용자의 입력 파일이 NUL로 구분 된 경우 -이 문자 개행 문자가 포함 된 파일 이름을 참조 할 수 있도록 허용으로, 이상적입니다) :

globfiles <args.0sv | xargs -0 ls -l -- 
+0

'rc'와 함께 작동하는지 궁금해할까요? ... 그렇다면 Tom Duff이 자랑 스러울 것입니다. 아마도 두 분 사이에 약간의 먼 관계가 있을지도 모릅니다. –