여러 디렉터리의 동일한 파일 이름: 단 하나의 명령으로 동시에 다른 이름을 할당하는 방법은 무엇입니까?

여러 디렉터리의 동일한 파일 이름: 단 하나의 명령으로 동시에 다른 이름을 할당하는 방법은 무엇입니까?

저는 23개의 서로 다른 디렉터리를 가지고 있으며 각 디렉터리에는 allowed_hits.bam이라는 파일이 있습니다.

따라서 각 디렉터리에 고유한 이름을 생성해야 합니다. 예: 디렉터리 1의 경우 accept_hits.bam_1 디렉터리 2의 경우 allowed_hits.bam_2

이를 23회 반복합니다. 하나의 명령으로 이를 수행하는 쉬운 방법이 있습니까?

답변1

그리고 bash그리고find

find . -type f -name accepted_hits.bam -exec bash -c \
'i=0; for f; do (( ++i )); mv -- "$f" "${f}_$i"; done' _ {} +

답변2

디렉터리가 모두 동일한 상위 디렉터리에 있다고 가정하고 다음을 시도해 보세요.

$ for f in $(ls */accepted_hits.bam); do mv $f $(dirname $f)/$(dirname $f)-$(basename $f); done

답변3

아마도 를 사용할 것입니다 awk. 하지만 이는 옳고 그름이 아닌 취향의 문제일 뿐입니다.

find . -name accepted_hits.bam | awk '{ print "cp -pi \"" $0 "\" \"" $0 "\"_" NR "; mv -i \"" $0 "\"_" NR " ./bam-files/" }' | tcsh -f

./bam-files/위 라인을 호출하기 전에 디렉터리를 생성하거나 디렉터리 이름을 조정 해야 합니다 . 만일의 경우에 대비해 -p파일 시간을 보존하고 덮어쓰기를 방지하기 위해 특별히 이것을 사용합니다 -i. 따라서 명령을 두 번째로 호출하기 전에 대상 디렉터리를 정리하십시오.

cp -pi원본 파일 을 삭제하려면 mv -i.

basename경로 이름에 특수 문자가 포함되어 있을 때 발생하는 문제를 줄이기 위해 스크립트에서는 호출을 생략합니다 (공백과 대부분의 특수 문자가 처리됨).

| tcsh -cf추신: 마지막을 생략하여 실행하기 전에 테스트 실행을 수행할 수도 있습니다 . 아직 설치 하지 않았다면 tcsh(예, 설치되지 않은 일부 Linux가 있습니다) 자유롭게 sh또는 를 사용하세요 bash.

답변4

Shell glob을 사용하면 이 작업을 쉽게 수행할 수 있습니다.

  1. 이름( accepted_hits.bam.1accepted_hits.bam.2)에 카운터를 추가합니다.

    c=0; for f in */accepted_hits.bam; do mv "$f" "$f".$((++c)); done
    

    설명하다

    accepted_hits.bam이는 단순히 현재 디렉터리의 하위 디렉터리에 있는 모든 호출된 파일을 반복 하고 각 파일 을 $f.$((++c))$c$f.$((++c))file.1file.2

    참고 c=0로 저는 . 이렇게 하지 않으면 후속 실행에서 값이 유지되고 $c계속해서 증가합니다.

  2. 확장자( 등) 앞에 카운터를 추가 accepted_hits.1.bam합니다 accepted_hits.2.bam.

    c=0; for f in */accepted_hits.bam; do  
        mv "$f" "$(dirname "$f")"/"$(basename "$f" .bam)".$((++c)).bam
    done
    

    설명하다

    이 명령은 dirname파일의 상위 디렉터리에 대한 경로를 반환합니다.

    $ dirname /usr/local/bin/apt 
    /usr/local/bin
    

    이 명령 basename은 반대입니다. 디렉터리를 제거하고 경로의 마지막 부분만 유지하며 확장자도 제거합니다.

    $ basename /etc/apt/sources.list
    sources.list
    $ basename /etc/apt/sources.list .list   ## remove extension
    sources
    

    따라서 mv "$f" "$(dirname "$f")"/"$(basename "$f" .bam)".$((++c)).bam필요에 따라 파일 이름이 변경됩니다.

  3. 상위 디렉터리의 이름( 또는 디렉터리 이름이 무엇이든)을 추가 accepted_hits.dir1.bam합니다 accepted_hits.dir2.bam.

    for f in */accepted_hits.bam; do  
        dir="$(dirname "$f")"; mv "$f" "$dir"/"$(basename "$f" .bam)"."$dir".bam
    done
    

    설명하다

    이는 파일 이름의 일부로 사용하기 쉽게 하기 위해 디렉터리 이름을 변수로 저장한다는 점을 제외하면 위와 같은 아이디어입니다.

  4. 외부 도구를 사용하십시오. Perl을 rename예로 들어 보겠습니다. Debian 기반 배포판과 함께 제공되는 표준은 rename증가하는 카운터를 처리할 수 없습니다. 그러나 나는 발견했다이것작동합니다. 이 페이지에 링크된 스크립트를 다운로드하여 increname현재 디렉터리에 저장하고 다음과 같이 실행합니다.

    perl increname -n 's/.bam/++$c . ".bam"/e' */accepted_hits.bam 
    

관련 정보