쉘 변수는 경로를 보유합니다. 파일 이름 부분을 어떻게 얻을 수 있나요?
bash(1)에서 나는 실험을 통해 환경 변수의 이름이 ."${i/*\///}"
어디에 있는지 를 통해 수행할 수 있다는 것을 발견했습니다 . i
이러한 접근 방식은 추악할 뿐만 아니라 /
경로에 문자가 포함되어 있지 않은 경우에도 잘못된 것입니다.
그러한 기능이 필요한 실제 사례를 보여드리겠습니다. 소스 디렉토리의 각 PDF 파일에 대해 현재 디렉토리에 대한 심볼릭 링크를 생성한다고 가정합니다.
$ for i in /source/path/*.pdf; do\
ln -s "$i" ."${i/*\///}"; \
done
답변1
${i##*/}
bash
이는 , dash
, 등을 ksh
포함한 Posix 쉘에 적용됩니다 . zsh
표준에서POSIX 매개변수 확장 섹션Posix 쉘 및 유틸리티 사양:
${매개변수##[단어]}
최대 접두사 패턴을 제거합니다. 패턴을 생성하려면 단어를 확장해야 합니다. 그런 다음 매개변수 확장을 통해 접두사의 가장 큰 부분이 제거된 패턴과 일치하는 매개변수를 생성해야 합니다.
또는 전통적으로 basename
이 목적으로 명령이 사용되었습니다. 경고하다:basename
외부 명령(예: )으로 구현되므로 성능이 중요한 문제가 될 수 있습니다 /usr/bin/basename
. 루프 내에서 이 작업을 수행하므로 각 파일에 대해 외부 명령을 호출하게 됩니다. 1000개 파일 목록의 경우 이는 basename
0.05초(매개변수 확장)와 2.0초(명령) 사이의 차이가 될 수 있습니다. 그러나 10,000개의 파일 목록의 경우 이는 0.5초(확장)와 20초()의 차이일 수 있습니다 basename
. 파일 수가 증가할수록 성능 차이는 더욱 극심해집니다.
가독성과 성능을 위해 다음과 같은 고유한 기능을 구현할 수 있습니다 basename
.
mybasename() { echo "${1##*/}"; }
(전체 명령줄 인터페이스의 기능 및/또는 basename
구현에 대해 더 나은 이름을 선택하는 것은 독자의 연습 문제로 남겨집니다. :)
답변2
경로를 변수에 넣고 해당 길이 수를 사용하여 다음과 같이 전체 경로 이름에서 필요한 하위 문자열만 가져올 수 있습니다.
$ pth="/source/path/";
$ for i in $path*.pdf; do \
ln -s "$i" ./"${i:${#pth}}"; \
done