パス名でファイル名を変更する

パス名でファイル名を変更する

サブフォルダ内に .bdf ファイルがあります。すべての .bdf は同じ名前です: Loads.bdf

例:

/home/user/folderxx/folderxxx/Load.bdf
/home/user/folderxx/folderxxx/Load.bdf

すべての Load.bdf ファイルを検索し (新しいフォルダーにコピーし)、そのパス名で名前を変更する必要があります。

例: 意図した操作の後、次のように表示されます。

folder001_folderAAA_Load.bdf
folder002_folderBBB_Load.bdf

答え1

そのために、(「複数移動」) パッケージmcpのツールを使用します。mmv

mcp '/home/user/*/*/Load.bdf' '#1_#2_Load.bdf'

2 番目の文字列のなどは#1#2最初の文字列の対応する 1 番目、2 番目などのワイルドカードの内容に置き換えられます。パスは一重引用符で囲まれているため、ワイルドカードはmcpシェルではなく によって解釈されることに注意してください。

表示されているコマンドでは、ファイルは現在のディレクトリにコピーされます。mcpを に置き換えるとmmv、ファイルは移動されます。

答え2

prename(多くのシステムでは に別名が付けられています)を使用すると、 またはrenameを複数回実行しなくてもこれを実行できます。mvcp

cd /home/user
find . -type f -name 'Loads.bdf' -exec \
  prename -n 's:^./::; s:/:_:g; s:^:destination/:' {} +

-n必要なファイルが移動されていることを確認したら、を削除します。

アップデート

ファイルを移動するのではなくコピーする場合、最初にcpioまたは を使用してコピーしpax、次に前と同じように名前を変更するのが最も速い方法です。例 (GNU を使用cpio):

cd /home/user
find . -type f -name 'Loads.bdf | cpio -p --make-directories destination

cd destination
find . -type f -name 'Loads.bdf' -exec  prename -n 's:^./::; s:/:_:g' {} +

paxは POSIX と LSB の両方であり、cpioもはや POSIX ではありませんが、cpio依然として多くのシステムで一般的に見られるプログラムであることに注意してください。

GNU find/で改行を含むファイル名を処理するには、 にとにcpio追加することができます。-print0find-0cpio

アップデート2

解決pax策はワンライナーです( は含みませんcd)。

cd /home/user
find . -name 'Loads.bdf' | cut -d/ -f 2- | pax -rws ':/:_:g' destination

または任意のファイル名(および GNU find)の場合:

find /home/user -name 'Loads.bdf' -printf '%P\0' | pax -0rws ':/:_:g' destination

答え3

他の回答で言及されているツール (mcp や mmv、prename など) がないシステムでこれを行う必要があり、これをすべてシェル内で実行したい場合は、次のようにします。

#!/usr/bin/env bash

oldpath="/home/user"
newpath="/home/user/newfolder"

for file in $(find $oldpath -type f -name Load.bdf); do
        shortname=${file#$oldpath/}
        newname="$newpath/${shortname//\//_}"
        if [ -f $newname ]; then
                echo "$newname already exists."
        else
                echo "copy: $file"
                echo "  --> $newname"
                cp $file $newname
        fi
done

Load.bdfこのスクリプトは、ディレクトリ内で名前が付けられたすべてのファイルを検索しoldpath、ディレクトリ名を新しいファイル名に変更して、宛先ディレクトリにコピーします。また、複数回実行する必要がある場合に備えて、すでにコピーされたファイルの存在をチェックすることもできます。これにより、すべてのファイルを再度コピーする必要がなくなります。

結果として得られるディレクトリ構造は次のようになります。

bash$ find . -type f
/home/user/folder001/folderAAA/Load.bdf
/home/user/folder002/folderBBB/Load.bdf
/home/user/folder003/folderCCC/Load.bdf
/home/user/newfolder/folder001_folderAAA_Load.bdf
/home/user/newfolder/folder002_folderBBB_Load.bdf
/home/user/newfolder/folder003_folderCCC_Load.bdf

答え4

env - sh <<\SCRIPT

    t=/home/user/target f=folder
    cd "${t%/*}" && mkdir -p "$t"
    set -- $f??/$f???/Load.BDF
    while [ -e "$1" ] ; do
        cp "$1" "$t/$(IFS=/
            printf '%s_%s_%s\n' $1)"
    shift ; done

SCRIPT

これはすべて完全に移植可能なシェル スクリプトだと思います。最初は疑問に思いましたが、非常に簡単に実行できます。

関連情報