다른 파일을 기반으로 여러 파일의 이름 바꾸기

다른 파일을 기반으로 여러 파일의 이름 바꾸기

약 300개의 파일이 들어 있는 폴더가 있습니다.

PD26414b.fixedheader.hs37d5.cram
PD26414b.fixedheader.hs37d5.cram.crai
PD26415g.fixedheader.hs37d5.cram
PD26415g.fixedheader.hs37d5.cram.crai

파일 이름의 ID(PD26414b, PD26415g)를 텍스트 파일에 저장한 것과 동일한 원본 이름으로 바꾸고 싶습니다.

head names.homologs.txt
PD26414b SAMEA3471115
PD26415g SAMEA3471120
PD26433c SAMEA3471126
PD26429d SAMEA3471130

따라서 PD26414b의 동족체 이름은 SAMEA3471115입니다.

제가 원하는 파일명은

SAMEA3471115.fixedheader.hs37d5.cram
SAMEA3471115.fixedheader.hs37d5.cram.crai
SAMEA3471120.fixedheader.hs37d5.cram
SAMEA3471120.fixedheader.hs37d5.cram.crai

Linux에서 이를 수행할 수 있는 방법이 있습니까? sed와 mv의 조합이어야 한다는 것을 알고 있지만 정확한 명령을 모릅니다.

답변1

이름 바꾸기 유틸리티가 설치되지 않은 경우 언제든지 자체적으로 롤아웃할 수 있지만 추가 기능은 없습니다.

perl -le 'local $/;
  my %h = <STDIN> =~ /^(.*) (.*)$/mg;
  rename $_, s/^[^.]+/$h{$&}/r
    for @ARGV;
' *cram* < names.homologs.txt

Pearl의 표준 입력에 있는 원본 파일을 사용하여 이름 맵 해시를 초기화하고 이를 후속 이름 바꾸기 명령에 적용할 수 있습니다.


파일 이름에 개행 문자가 없으므로 sed를 사용하여 이를 수행할 수 있습니다.

sed -Ee '
  1i\
h
  s|\S+|s/^[.][/]&[.]/|
  s||.\\/&./;ta|2
$a\
:a\
G\
s/(.*)\\n(.*)/\\2 \\1/
' names.homologs.txt > genMvPairs

  find . -maxdepth 1 -type f -name '*.cram*' |
  sed -Ef genMvPairs - | xargs -n2 -t mv -f

답변2

Linux 시스템을 사용 중이거나 perl rename 명령( 운영 체제에 따라 또는 이라고 부를 수 있음)에 액세스할 수 있고 ID에 공백이나 기타 공백이 있을 수 없다고 가정하면 다음을 수행할 수 rename있습니다 prename. perl-rename수행원:

while read id hom; do
    rename -n "s/^$id/$hom/" "$id".*
done < names.homologs.txt

이는 수행할 작업을 인쇄할 뿐 실제로 이름을 바꾸지는 않습니다. 요구 사항을 충족하는지 확인한 후에는 -n실제로 변경하도록 선택하지 않고 다시 실행하세요.


또는 셸에서 다음을 수행할 수 있습니다.

while read id hom; do
    for file in "$id".*; do
        newFile=$(printf '%s\n' "$file" | sed "s/$id/$hom/")
        mv -- "$file" "$newFile"
    done
done < names.homologs.txt

그러나 이는 이름 충돌이 없고(파일의 새 이름이 기존 파일 이름과 일치하는 경우 기존 파일을 덮어쓰게 됨) 파일 이름에 개행 문자가 없다고 가정합니다(파일의 새 이름이 기존 파일 이름과 일치함). 임시 파일을 사용하면 실제로 안전해야 합니다. 가정).

답변3

이는 하반기와 비슷한 것으로 나타났다.테든의 답변하지만 저는 파일의 새 이름을 계산하는 데 더 안전하고 빠른 방법을 사용하고 있습니다.

사용 /bin/sh:

#!/bin/sh

while read -r id homolog; do
        for oldname in "$id".*; do
                [ -e "$oldname" ] || continue
                newname=$homolog.${oldname#$id.}
                mv -- "$oldname" "$newname"
        done
done <names.homologs.txt

이는 이름을 바꾸려는 파일이 현재 디렉터리에 있다고 가정합니다. 스크립트는 파일의 각 줄에서 두 문자열을 읽어 names.homologs.txt두 개의 변수 idsum 으로 읽습니다 homolog.

각각에 대해 일치하는 이름을 가진 현재 디렉터리의 파일을 id통해 루프를 시도합니다 . "$id".*이러한 각 파일에 대해 존재하는 경우 유틸리티를 사용하여 $id.문자열의 시작 부분에 있는 부분을 .$homolog.mv

이름 충돌은 확인되지 않습니다.

답변4

bash@terdon이 말했듯이 파일 이름에 이상한 문자가 없고 수많은 동족체가 없는 순수한 솔루션은 다음과 같습니다.

#!/usr/bin/env bash

declare -a homologs

while read key val
do {
  homologs["$key"]="$val"
} done < names.homologs.txt


while read file
do
# key is the part before the dot
  key="${file%%.*}"
# end is part after the first dot to the end
  end="${file#*.}"
  printf 'mv -- "%s" "%s.%s"\n' "${file}" "${homologs["$key"]}" "$end"
done

관련 정보