`compgen -G ...와 함께 -I 매개변수 xargs basename을 사용해야 하는 이유 |

`compgen -G ...와 함께 -I 매개변수 xargs basename을 사용해야 하는 이유 |

compgen -Ga의 출력을 파이핑했지만 xargs basename아래와 같이 매개변수를 추가할 때까지 작동하지 못하는 상황이 발생했습니다. xargs -I다음은 설명 주석과 함께 제가 하려는 작업을 보여주는 스크립트입니다. 두 가지 질문이 있습니다. 해당 질문은 스크립트 뒤에 나타납니다.

# create three files for testing:
touch /tmp/my.file.1.2.txt
touch /tmp/1.my.file.2.txt
touch /tmp/1.2.my.file.txt

# create a glob and verify that it works with compgen:
glob=/tmp/*.file*.txt
compgen -G "$glob"

#output:
/tmp/1.2.my.file.txt
/tmp/1.my.file.2.txt
/tmp/my.file.1.2.txt

# try to get the basename of each file using xargs.
# I thought this would work, but it does not.
compgen -G "$glob" | xargs basename

#output:
basename: extra operand ‘/tmp/my.file.1.2.txt’
Try 'basename --help' for more information.

# eventually I discovered that this would work.
# however, I don't understand why this would work
# but the previous attempt would not, since I
# think that this command is just a more
# explicitly-specified version of the previous 
# one.
compgen -G "$glob" | xargs -I{} basename {}

#output:
1.2.my.file.txt
1.my.file.2.txt
my.file.1.2.txt

xargs다른 명령은 매개변수 없이 사용할 수 있습니다 -I. 예를 들어, compgen -G "$glob" | xargs ls -al훌륭하게 작동합니다.

basename질문 1: 이 스크립트에 필요한 매개변수는 무엇입니까 -I?

질문 2: 이 결과를 보기 전에는 와 가 서로 동의어라고 생각했는데, 그렇지 않은 것 xargs basename같습니다 . xargs -I{} basename {}차이점은 무엇입니까?

이것이 문제가 될지는 의문이지만 만일의 경우에 대비해 이 문제는 bash 5.0.17(1) 릴리스를 실행하는 Ubuntu 20.04.4(5.13.0-35-generic)에서 발생합니다.

이 파일 목록을 생성하는 다른 방법이 있다는 것을 알고 있지만, 앞으로 오류를 방지하기 위해 이해해야 할 기본 사항을 여기서 분명히 이해하지 못하기 때문에 걱정됩니다.

답변1

POSIXbasename한 번에 하나의 이름만 처리되며 선택적으로 접미사를 제거합니다. 한 번에 최대한 많은 인수를 실행하려고 xargs basename시도 하지만 실패하여 처리를 위해 각 이름이 한 번 실행됩니다.basenamexargs -I{} basename {}xargsbasename

출력 비교

printf "foo\nbar\nbaz" | xargs echo basename

그리고

printf "foo\nbar\nbaz" | xargs -I{} echo basename {}

GNU는 basename접미사를 지정할 필요가 없는 경우 여러 이름을 허용하는 여러 옵션을 지원합니다.

xargs basename -a

이렇게 하면,

xargs basename -s .suffix

관련 정보