Linux 'find'에서만 파일 이름을 얻는 방법은 무엇입니까?


266

디렉토리의 모든 파일에 find를 사용하고 있으므로 경로 목록을 얻습니다. 그러나 파일 이름 만 필요합니다. 즉 나는 얻고 ./dir1/dir2/file.txt싶다file.txt

답변:


359

GNU에서는 find다음 -printf과 같은 매개 변수를 사용할 수 있습니다 .

find /dir1 -type f -printf "%f\n"

9
분명히 대답 이지만 세부 사항이 없습니다.
Jason McCreary

25
이것은 GNU 전용입니다
Osama F Elias

3
여러 파일 형식 (-o 스위치)을 사용할 때이 기능이 작동하지 않습니다
Urchin

9
알 수없는 차 또는 운영자 : -printf : 찾을
HOLMS

@Urchin 당신이 올바른 논리를 가지고있는 한 (즉 , -o묵시적인 것보다 우선 순위가 낮기 -a때문에 종종 -o논쟁 을 그룹화하고 싶을 것입니다. )
Monica Reinstate Monica Please

157

find에 -printf 옵션이없는 경우 basename을 사용할 수도 있습니다.

find ./dir1 -type f -exec basename {} \;

17
세미콜론을 인용하는 것은 명확하게하는 또 다른 방법입니다.... {} ';'
davidchambers

28

다음 -execdir과 같이 현재 파일을 자동으로 보유하는 다음 을 사용하십시오 {}.

find . -type f -execdir echo '{}' ';'

$PWD대신 사용할 수도 있습니다 .(일부 시스템에서는 전면에 추가 점이 생성되지 않음).

여전히 추가 점이 있으면 다음을 실행할 수 있습니다.

find . -type f -execdir basename '{}' ';'

-execdir utility [argument ...] ;

-execdir주는 동일 -exec유틸리티는 디렉토리에서 실행됩니다 것을 제외하고 주 현재 파일을 보유 .

사용하는 경우 +대신 ;다음 {}유틸리티를 호출 할 때마다 가능한 한 많은 경로 이름으로 대체됩니다. 즉, 모든 파일 이름을 한 줄에 인쇄합니다.


./filename대신에 받고 filename있습니다. 필요에 따라 괜찮을 수도 있고 아닐 수도 있습니다.
user276648

@ user276648 $PWD대신에 사용해보십시오 ..
kenorb

24

GNU find를 사용하는 경우

find . -type f -printf "%f\n"

또는 Ruby (1.9+)와 같은 프로그래밍 언어를 사용할 수 있습니다

$ ruby -e 'Dir["**/*"].each{|x| puts File.basename(x)}'

bash (최소 4) 솔루션을 좋아한다면

shopt -s globstar
for file in **; do echo ${file##*/}; done

sleske 도움을 주신 귀하의 답변에 영감을 받았습니다 : serverfault.com/a/745968/329412
Nolwennig

11

파일 이름에 대해서만 일부 작업을 실행하려면 사용하기 basename가 어려울 수 있습니다.

예를 들면 다음과 같습니다.

find ~/clang+llvm-3.3/bin/ -type f -exec echo basename {} \; 

basename 만 에코 /my/found/path합니다. 파일 이름을 실행하려면 원하는 것이 아닙니다.

그러나 xargs출력 할 수 있습니다 . 예를 들어 다른 디렉토리의 이름을 기반으로 디렉토리의 파일을 종료하려면 다음을 수행하십시오.

cd dirIwantToRMin;
find ~/clang+llvm-3.3/bin/ -type f -exec basename {} \; | xargs rm

그나마 에코 -find ~/clang+llvm-3.3/bin/ -type f -exec basename {} \;
commonpike

7

Mac (BSD find)에서는 다음을 사용하십시오.

find /dir1 -type f -exec basename {} \;

1

-exec그리고 -execdir느린, xargs왕이다.

$ alias f='time find /Applications -name "*.app" -type d -maxdepth 5'; \
f -exec basename {} \; | wc -l; \
f -execdir echo {} \; | wc -l; \
f -print0 | xargs -0 -n1 basename | wc -l; \
f -print0 | xargs -0 -n1 -P 8 basename | wc -l; \
f -print0 | xargs -0 basename | wc -l

     139
    0m01.17s real     0m00.20s user     0m00.93s system
     139
    0m01.16s real     0m00.20s user     0m00.92s system
     139
    0m01.05s real     0m00.17s user     0m00.85s system
     139
    0m00.93s real     0m00.17s user     0m00.85s system
     139
    0m00.88s real     0m00.12s user     0m00.75s system

xargs평행도 도움이됩니다.

충분히 재미있게 난의 마지막 경우 설명 할 수 xargs없는이 -n1. 올바른 결과를 제공하며 가장 빠릅니다.¯\_(ツ)_/¯

( basename단 1 경로 인수를 취하는 그러나 xargs없이 실제로 5000 모든 ()을 보내드립니다 -n1.이 작동하지 않음을 리눅스와 오픈 BSD에 만 맥 OS ...)

리눅스 시스템에서 몇 가지 더 큰 숫자가 -execdir도움이되는 방법 을 알지만 병렬보다 훨씬 느립니다 xargs.

$ alias f='time find /usr/ -maxdepth 5 -type d'
$ f -exec basename {} \; | wc -l; \
f -execdir echo {} \; | wc -l; \
f -print0 | xargs -0 -n1 basename | wc -l; \
f -print0 | xargs -0 -n1 -P 8 basename | wc -l

2358
    3.63s real     0.10s user     0.41s system
2358
    1.53s real     0.05s user     0.31s system
2358
    1.30s real     0.03s user     0.21s system
2358
    0.41s real     0.03s user     0.25s system

1
또 하나의 데이터 포인트 : 오픈 BSD에 긴 실행 find그것이 -execdir새로운 프로세스를 생성하는 것은 상대적으로 비용이 많이 드는 작업이기 때문에 그 가장 빠른됩니다.
빼기

1

정직 basenamedirname솔루션은 쉽게,하지만 당신이 체크 아웃 할 수 있습니다 :

find . -type f | grep -oP "[^/]*$"

또는

find . -type f | rev | cut -d '/' -f1 | rev

또는

find . -type f | sed "s/.*\///"

0

다른 사람들이 지적했듯이 find및 을 결합 할 수 basename있지만 기본적으로 basename프로그램은 한 번에 하나의 경로에서만 작동하므로 실행 파일은 각 경로마다 한 번만 실행해야하며 ( find ... -exec또는을 사용하여 find ... | xargs -n 1) 잠재적으로 느릴 수 있습니다.

-aon 옵션 을 사용하면 basename한 번의 호출로 여러 파일 이름을 사용할 수 있습니다. 즉,을 사용 xargs하지 않고 -n 1경로를 훨씬 더 적은 수의 호출로 그룹화하여 basename보다 효율적으로 사용할 수 있습니다.

예:

find /dir1 -type f -print0 | xargs -0 basename -a

여기 에는 파일과 디렉토리 이름 내부의 공백에 대처하기 위해 -print0and -0(함께 사용해야 함)를 포함 시켰습니다 .

다음은 버전 xargs basename -axargs -n1 basename버전 간의 타이밍 비교 입니다. (유사와 유사한 비교를 위해 여기에보고 된 타이밍은 초기 더미 실행 후이므로 파일 메타 데이터가 I / O 캐시에 이미 복사 된 후에 모두 수행됩니다.) cksum두 경우 모두, 출력이 사용 된 방법과 독립적이라는 것을 보여주기 위해.

$ time sh -c 'find /usr/lib -type f -print0 | xargs -0 basename -a | cksum'
2532163462 546663

real    0m0.063s
user    0m0.058s
sys 0m0.040s

$ time sh -c 'find /usr/lib -type f -print0 | xargs -0 -n 1 basename | cksum' 
2532163462 546663

real    0m14.504s
user    0m12.474s
sys 0m3.109s

보시다시피 basename매번 실행을 피하는 것이 실제로 훨씬 빠릅니다 .


@minusf의 답변을 더 자세히 읽으면 Mac에서 basename추가 명령 줄 인수가 필요없이 여러 파일 이름을 사용할 수 있음을 알 수 있습니다. 의 사용 -a여기에 리눅스에 있습니다. ( basename --version나에게 말한다 basename (GNU coreutils) 8.28.)
alaniwi

-3

makandracards 페이지에서 최신 파일 이름을 제공하는 솔루션을 찾았습니다.

ls -1tr * | tail -1

(감사 Arne Hartherz에 간다)

나는 그것을 위해 사용했다 cp:

cp $(ls -1tr * | tail -1) /tmp/

2
이것은 전혀 질문에 대답하지 않습니다.
kenorb
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.