파일에 보유 된 경로 목록을 구문 분석하려면 basename을 사용하십시오.


9

Mac OSX를 실행 중이며 명령 줄을 사용하여 이름이 같은 파일 수를 찾습니다.

다음 명령을 사용하려고했습니다.

find ~ -type f -name "*" -print | basename | sort | uniq -d > duplicate_files

작동하지 않습니다! 내가 다음을 할 때 :

find ~ -type f -name "*" -print > duplicate_files

그런 다음 duplicate_files에는 모든 파일의 경로가 포함됩니다. 따라서 문제는 basename표준 입력을 허용하지 않습니다. 그런 다음 다음을 시도했습니다.

basename $(find ~ -type f -name "*" -print) > duplicate_files

그러나 다시는 작동하지 않는 것 같습니다. 인터넷 검색은 큰 기쁨을 얻지 못하는 것 같습니다. 어떤 생각이라도 가장 환영합니다.

답변:


16

basename 명령 행 인수에서 작동하며 표준 입력에서 읽지 않습니다.

basename유틸리티 를 호출 할 필요가 없으며 더 나은 방법은 아닙니다. 마지막 전에 부분을 제거하고 /각 항목에 대해 외부 명령을 호출하는 것이 느릴 것입니다. 텍스트 처리를 사용할 수 있습니다 대신 유틸리티.

find ~ -type f | sed 's!.*/!!' | sort | uniq -d

파일 위치를 추적하는 것이 더 유용 할 수 있습니다. 이름별로 정렬하면 중복을 쉽게 찾을 수 있지만 sort마지막 필드를 사용할 수있는 옵션이 없습니다. 당신이 할 수있는 일은 마지막 /으로 구분 된 필드를 처음으로 복사 한 다음 정렬 한 다음 약간의 임시 처리를 사용하여 복제본을 추출하고 제시하는 것입니다.

find ~ -type f |
sed 's!.*/\(.*\)!\1/&!' |   # copy the last field to the beginning
sort -t/ -k1,1 |
cut -d/ -f2- |   # remove the extra first field (could be combined with awk below)
awk -F / '{
    if ($NF == name) {
        if (previous != "") {print previous; previous = ""}
        print
    } else {
        previous = $0
        name = $NF
    }
'

(파일 이름에 개행 문자가 포함되어 있지 않다고 가정합니다.)


정말 고마워 이것이 바로 내가하려는 일입니다 ... 매우 유용합니다
JohnB

7

내장 find기능 을 사용 하여 파일 이름 만 출력 하지 않는 이유는 무엇입니까?

find ~ -type f -printf '%f\n' | sort | uniq -c

(GNU 가정 find) 또는 적어도 다음과 같은 것 :

find ~ -exec basename {} \; | sort | uniq -c

basename 파이프를 통해 읽거나 여러 파일을 한 번에 처리 할 수 ​​없습니다.

추신. -name '*'모든 파일을 나열하려는 경우 지정할 필요가 없습니다 . 이것이 기본 옵션입니다.


감사합니다- '-printf'는 OS X UNIX에서 작동하지 않습니다
JohnB

그리고 두 번째 버전을 시도하면 얻을 수 basename: unknown primary or operator있습니다. 팁을 주셔서 감사합니다-name "*"
JohnB

이상하다. -printfposix 매뉴얼 페이지에서도 볼 수 있습니다 . 두 번째 방법으로 오류에 대해서는 내 대답에 오타가 있습니다. 결정된. 한번 더 시도해 주시겠습니까?
러시

또한 함께 -printfi를 얻을 -printf: unknown primary or operator. 또한 Nutshell 참고서에서 유닉스를 확인했을 때 GNU / Linux 옵션으로 나열되어 있습니다. OSX에 대해서는 아무 말도하지 않습니다
JohnB

1
실제로 가장 좋은 소스는 man find당신의 콘솔에 있을 것 입니다 :)
rush

4

이것은 OSX에서 나를 위해 작동하는 것 같습니다 :

find ~ -type f -exec basename -a {} + | sort | uniq -d

그렇습니다-이것은 매우 감사합니다-관심이 +없다면 명령에서 무엇을 의미합니까?
JohnB

2
유용하다고 생각하십니까?
suspectus

그것은-나는 beacuase를 투표 할 수 없다 나는 15의 명성이 필요하다 :-(
JohnB

@StephaneChazelas : BSD basenameman 페이지에 따르면 , 실행 파일은 여러 문자열을 인수로 사용할 수 있습니다. OSX를 두 번 확인했는데 작동합니다.
rahmu

1
알겠습니다 미안 해요 나는 그 BSD 확장을 몰랐다. 그러나 정확히 두 개의 파일이 있으면 여전히 실패합니다. 해당 사례를 다루는 -a옵션 을 추가해야합니다 .
Stéphane Chazelas

2

대안 (파일 이름에 줄 바꿈이 없다고 가정) :

find ~ -type f | awk -F/ '{print $NF}' | sort | uniq -d

2

xargswith basename를 사용 하여 다음과 같이 원하는 출력을 얻을 수 있습니다 .

find ~ -type f -name "*" -print | xargs -l basename | sort | uniq -d > duplicate_files

0

최신 버전의 bash연관 배열을 처리하면 다음과 같이 개행 문자가 포함 된 경로 이름을 추가로 처리 할 수 ​​있습니다.

#!/bin/bash

topdir=$HOME

shopt -s globstar  # enable the ** glob

declare -A count

# count the number of times each filename (base name) occurs
for pathname in "$topdir"/**; do
    # skip names that are not regular files (or not symbolic links to such files)
    [ ! -f "$pathname" ] && continue

    # get the base name
    filename=${pathname##*/}

    # add one to this base name's count
    count[$filename]=$(( ${count[$filename]} + 1 ))
done

# go through the collected names and print any name that
# has a count greater than one
for filename in "${!count[@]}"; do
    if [ "${count[$filename]}" -gt 1 ]; then
        printf 'Duplicate filename: %s\n' "$filename"
    fi
done

이것은 외부 유틸리티를 사용하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.