다음을 사용하면 basename {} .txt
작동합니다 .
find . -iname "*.txt" -exec basename {} .txt \;
xxx
대신에 인쇄됩니다 ./xxx.txt
. 옵션을 사용하면 $(basename {} .txt)
실패 -exec
합니다.
find . -iname "*.txt" -exec echo "$(basename {} .txt)" \;
그냥 인쇄될 거예요./xxx.txt
이 문제를 어떻게 해결할 수 있나요? $(basename {} .txt)
다른 cmd의 매개변수 로 사용할 수 있기를 바랍니다 . 조작이나 파이핑을 위해 xargs를 사용해야 합니까 sh -c
?-exec basename {} \;
답변1
노력하다:
find -iname "*.txt" -exec sh -c 'for f do basename -- "$f" .txt;done' sh {} +
첫 번째 명령은 $(...)
하위 쉘에서 실행될 때 {}
리터럴로 처리되기 때문에 실패합니다. 따라서 basename {} .txt
돌아 오면 {}
다음과 find
같습니다.
find . -iname "*.txt" -exec echo {} \;
어떤 인쇄 파일 이름이 일치합니까?
답변2
$()
및 작은따옴표를 사용하는 경우에도 sh -c
명령 대체를 사용할 수 있습니다.
find . -iname "*.txt" -exec sh -c 'echo "$(basename {} .txt)"' \;
작은따옴표는 메인 쉘이 그 안에 있는 하위 명령을 실행하는 것을 방지하므로 $()
다음을 전달할 수 있습니다.sh -c
뒤쪽에명령 이 파일 이름으로 find
대체되었습니다 . {}
바라보다스택 오버플로에 대한 이 답변더 자세한 설명을 위해.
$()
파일 이름에 공백을 처리하기 위해 큰따옴표를 추가할 수도 있습니다 .
find . -iname "*.txt" -exec sh -c 'echo "$(basename "{}" .txt)"' \;
답변3
xargs
대신 bash 파이프와 명령을 사용하는 다른 방법이 있습니다 .
find . -iname '*.txt' | xargs -L1 -I{} basename "{}"
xargs
위 명령 에서 :
매개변수는 -L1
한 줄씩 실행되는 명령줄의 출력을 나타냅니다 find
.
이 매개변수는 bash 토큰화(파일 이름에 공백이 포함된 경우)를 방지하기 위해 명령 출력을 큰따옴표로 묶기 -I{}
위한 것입니다 .find
답변4
파이핑이 더 쉽기 때문에(입력, 기억, 읽기 등) @an9wer에 동의합니다. 예를 들어 posix xargs를 준수하고 구분 기호로 nil 문자를 사용하려고 노력하지만, alpine의 xargs에는 태그가 없습니다 -L1
. 및 명령을 사용하려면 find
에 nil을 명시적으로 표시하세요 xargs
.
임시 명령 실행에 대해 이야기하는 경우 이를 무시하십시오. 그러나 이것이 프로덕션 환경이 아닌 환경에서 개발된 스크립트이고 프로덕션 환경이 절대 변경되지 않을 것이라고 가정하면 이는 실제로 큰 문제입니다.
@an9swer와 동일하지만 nil 문자를 구분 기호로 사용하고 -n
플래그를 사용하여 결과를 한 번에 하나씩 인수로 제공합니다 basename
. 또한 템플릿 플래그 -I
는 추론되고 기본 동작이므로 필요하지 않습니다 .
find . -iname '*.txt' -print0 | xargs -0 -n1 -- basename
위의 또 다른 장점은 xargs를 사용하면 전달된 명령문을 병렬로 실행할 수 있다는 것입니다. 즉, 일부 다운스트림 프로세스에 공급해야 하는 코어 수까지 위의 명령문을 병렬로 실행할 수 있습니다. 거의 무한한 수의 파일로 작업하거나 작업 흐름 최적화가 중요한 경우 이는 매우 큰 이점입니다.
네, 저는 좀 과시하는 편이지만 (가끔) 얌전할 수도 있으니 괜찮습니다.