저는 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을 사용하면 이 작업을 쉽게 수행할 수 있습니다.
이름(
accepted_hits.bam.1
등accepted_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.1
file.2
참고
c=0
로 저는 . 이렇게 하지 않으면 후속 실행에서 값이 유지되고$c
계속해서 증가합니다.확장자( 등) 앞에 카운터를 추가
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
필요에 따라 파일 이름이 변경됩니다.상위 디렉터리의 이름( 또는 디렉터리 이름이 무엇이든)을 추가
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
설명하다
이는 파일 이름의 일부로 사용하기 쉽게 하기 위해 디렉터리 이름을 변수로 저장한다는 점을 제외하면 위와 같은 아이디어입니다.
외부 도구를 사용하십시오. Perl을
rename
예로 들어 보겠습니다. Debian 기반 배포판과 함께 제공되는 표준은rename
증가하는 카운터를 처리할 수 없습니다. 그러나 나는 발견했다이것작동합니다. 이 페이지에 링크된 스크립트를 다운로드하여increname
현재 디렉터리에 저장하고 다음과 같이 실행합니다.perl increname -n 's/.bam/++$c . ".bam"/e' */accepted_hits.bam