異なるファイルに基づいて複数のファイルの名前を変更する

異なるファイルに基づいて複数のファイルの名前を変更する

約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ますprenameperl-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

これは、名前を変更したいファイルが現在のディレクトリにあると仮定します。スクリプトはファイルの各行から2つの文字列を読み取り、2つの変数names.homologs.txtsumidとして読み込みます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

関連情報