경로를 나열하지 않고 파일 이름을 나열하기 위해 find 명령을 사용하는 방법은 무엇입니까?

경로를 나열하지 않고 파일 이름을 나열하기 위해 find 명령을 사용하는 방법은 무엇입니까?

온라인에서 몇 가지 답변을 확인했지만 명령에 매개변수가 있으면 작동하지 않습니다 -name(아마 제가 뭔가 잘못하고 있는지 확실하지 않습니다). 내가 원하는 것은 파일 이름(디렉토리/경로가 아님)만 나열하는 것입니다. 더 복잡하게 만들기 위해 파일 이름은 같지만 확장자가 다르기 때문에 및를 -name사용하여 결과를 필터링 해야 합니다. -o질문은 내 제안입니다. 또는 -printf때로는 basename제대로 작동하지 않을 때도 있습니다 -name *.txt -o name *.pdf. 이 문제를 해결할 다른 방법이 있나요?

내 파일의 예:

/dir1/dir2/dir3/dir4/
                    /file1.txt
                    /file1.pdf
                    /file1.ods ...etc.

목록당 나열된 하나 이상의 유형의 파일에만 관심이 있습니다( -name.

단 1개의 명령으로 수행할 수 있습니까? find아니면 2단계로 수행해야 합니까(결과를 임시 파일에 저장한 다음 임시 파일에서 디렉터리를 필터링/제거)? 내가 달성하려는 작업의 결과는 각 줄에 파일 이름이 있는 텍스트 파일입니다.

file1.txt
file1.pdf
file1.ods
file2.txt
file2.pdf
etc.

내가 사용하는 명령은

find /dir1/dir2/dir3/dir4/ -type f -name '*.txt' -o -name '*.pdf' -o -name '*.ods' -printf "%f\n"

저는 GNU Find를 사용하고 있습니다.

고쳐 쓰다

\(...\)αГsнιι가 나에게 상기시켜 주듯이 를 넣어야 한다는 것이 밝혀졌습니다.

답변1

논리적 OR 패턴으로 여러 표현식을 사용하는 경우 -o해당 표현식을 모두 묶어야 합니다 \( ... \). 그렇지 않으면 마지막 표현식 결과가 항상 존중되며 -printf '%f\n'모든 선행 디렉터리가 제거된 파일 이름만 인쇄하는 데 사용됩니다.

find . -type f \( -name '*.pdf' -o -name '*.txt' \) -printf '%f\n'

바라보다man find아래에운영자다음 섹션과 관련하여 ( expr ):

운영자
...

(expr)
우선순위를 강제합니다. 괄호는 쉘에 특별하기 때문에 일반적으로 따옴표로 묶어야 합니다.

따라서 \( ... \)또는 '(' ... ')'(괄호 앞과 뒤의 공백이 중요함)을 사용하여 이스케이프할 수 있습니다.

답변2

-name이미 언급했듯이 테스트를 괄호 안에 그룹화 해야 합니다 . 이러한 괄호는 \( ... \)예를 들어 '(' ... ')'쉘로부터 보호하기 위해 이스케이프하거나 인용해야 합니다 (그렇지 않으면 하위 쉘을 지정하게 됩니다).

표준을 사용 find하고 파일 이름 접미사 처리를 약간 더 쉽게 만듭니다.

set -- txt pdf ods

for suffix do
    set -- "$@" -o -name "*.$suffix"
    shift
done
shift

find /dir1/dir2/dir3/dir4 \( "$@" \) -type f -exec basename {} \;

먼저 위치 인수를 보려는 파일 이름 접미사 목록으로 설정하고(또는 이것이 스크립트인 경우 명령줄에서 가져옵니다) -name테스트의 OR 목록을 구성합니다. 그런 다음 명령줄에서 사용하십시오 find.

그런 다음 명령 find자체는 basename발견된 각 이름에 대해 유틸리티를 호출합니다.

대안으로 매개변수 대체를 사용하여 각 경로 이름의 파일 이름 부분을 제외한 모든 것을 제거할 수 있습니다. 하지만 이렇게 하려면 경로 이름을 인라인 sh -c스크립트에 전달해야 합니다.

# [...] as before [...]

find /dir1/dir2/dir3/dir4 \( "$@" \) -type f -exec sh -c '
    for pathname do
        printf "%s\n" "${pathname##*/}"
    done' sh {} +

basename적어도 처리할 파일 이름이 많은 경우에는 사용된 변형보다 더 빠르게 실행될 것으로 기대합니다 . 하지만 GNU용 coreutils를 사용하면 다음 과 같이 basename사용할 수 있습니다 .-a--multiple

find /dir1/dir2/dir3/dir4 \( "$@" \) -type f -exec basename -a {} +

basename이는 가능한 한 적은 횟수로 호출됩니다 . 그러나 coreutils가 설치되어 있으면 GNU를 사용하여 동일한 작업을 수행하는 데 find사용할 수 있는 findutils를 설치할 수도 있습니다.-printf '%f\n'

관련 정보