複数のディレクトリの同じファイル名:単一のコマンドで同時に別の名前を割り当てる方法は?

複数のディレクトリの同じファイル名:単一のコマンドで同時に別の名前を割り当てる方法は?

私は23の異なるディレクトリを持ち、各ディレクトリにallowed_hits.bamというファイルがあります。

したがって、各ディレクトリに一意の名前を生成する必要があります。例: ディレクトリ 1 の場合 accept_hits.bam_1 ディレクトリ 2 の場合 allowed_hits.bam_2

これを23回繰り返します。 1つのコマンドでこれを行う簡単な方法はありますか?

答え1

そしてbashfind

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。したがって、コマンドを 2 番目に呼び出す前に、ターゲット ディレクトリをクリーンアップします。

cp -pi元のファイルを削除するにはmv -i

basenameパス名に特殊文字が含まれているときに発生する問題を減らすために、スクリプトは呼び出しを省略します(スペースとほとんどの特殊文字が処理されます)。

| tcsh -cfPS:最後を省略して実行する前にテスト実行を実行することもできます。まだインストールしていない場合tcsh(はい、インストールされていないLinuxがいくつかあります)、自由にshまたはを使用してくださいbash

答え4

Shell globを使用すると、これを簡単に実行できます。

  1. 名前(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.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 
    

関連情報