2016-04-26 9 views
0

パス内のファイルの一括改名中に問題が発生しました。ランダムに指定されたファイルのパス名を知らずに一括して名前を変更

ここに私の問題があります: 私は約16000以上のファイル(すべての画像がありますが、.psd、.jpg、.ai、.pngなど)が非常に乱雑な方法で散在しています。しかしファイル名は、ありがたいことにすべてがユニークですが、純粋な量のために、私は確信しています(つまり、abc.aiまたは同等の名前のファイルが2つありますが、多くはありません)。私はパスを知ることができません。提供されたcsvには元のファイル名だけが含まれていて、名前を変更する必要があるからです。

基本的には、CSVファイルの最初の行のようなものです:

qwerty.jpg、asdfg.jpg

または

123-asd_qwe.ai、abcfgd。 ai。

私はいくつかの解決策を試しました。いくつかのスクリプト、何か私は本当にやってみることができるもの。

私は本当に命題やアイデア、あるいは解決策を聞きたいです!注意することは

:私が試した::

sed 's/"//g' names.csv | while IFS=, read orig new; do echo mv "$orig" "$new"; done 

sed 's/^/mv -i -v "/;s/, /" "/;s/$/";/' < names.csv | bash - 

#!/bin/bash 
while read line   
do   
     OldImageName=${line%,*} 
     NewImageName=${line#*,} 
     mv "$OldImageName" "$NewImageName" 
done <"names.csv" 
+0

すべての二重引用符をsedコマンドで置き換えないのはなぜですか?ファイル内に引用符はありません。 – 123

+0

私は試していました。ちょうど巨大なcsvファイルにこれらのファイルが含まれているとします。 – frosty

答えて

0

これは、上で説明した特定のケースで動作している完全な解決策です。重複したファイル(異なるフォルダ内)を考慮し、ファイル名(空白、アクセントなど) 。下記の解決策を参照してください:

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 

while read line 
do 
    OldImageName=$(echo $line | cut -d "," -f 1) 
    NewImageName=$(echo $line | cut -d "," -f 2) 

    isMatchRelativePath=$(echo $(find . -name "$OldImageName")); 
    isMatchNewName=$(echo $(find . -name "$NewImageName")); 

    if [ ! -z "$isMatchRelativePath" ]; 
    then 

     find . -name "$OldImageName" -print0 | while read -d $'\0' file 
     do 

     relativeFolder="${file%$OldImageName}" 

     quote1="$relativeFolder$OldImageName"; 
     quote2="$relativeFolder$NewImageName"; 

     mv "${quote1}" "${quote2}" 
     echo "$relativeFolder$OldImageName, $relativeFolder$NewImageName">>"$DIR/success.csv" 
     done 


    elif [ ! -z "$isMatchNewName" ]; then 
     echo "alreadyRenamed" 
     echo "$relativeFolder$OldImageName, $relativeFolder$NewImageName">>"$DIR/alreadyRenamed.csv" 
    else 
     echo "failed" 
     echo "$relativeFolder$OldImageName, $relativeFolder$NewImageName">>"$DIR/failed.csv" 
    fi 

done <input.csv 
+0

これはでした。完璧。 – frosty

2

をあなたはnames.txtがで名前を持っているような方法の絶対的に確信している場合oldname,newnameを注文すれば、以下のロジックで十分です。 -

#!/bin/bash 

while read line 
do 
     # Splitting the line with delimiter as ',' and 
     # getting the fields before and after 

     OldImageName=$(echo $line | cut -d "," -f 1) 
     NewImageName=$(echo $line | cut -d "," -f 2) 

     if [ $(find . -name "$OldImageName" | wc -l) -gt 0 ]; then 

      # Get the absolute path of the file 

      path=$(dirname $(readlink -f "$OldImageName")) 

      # Verbose option '-v' for verifying the file rename and 
      # to suppress errors if file not present 

      mv -v "$path/$OldImageName" "$path/$NewImageName" 2>/dev/null 
     fi 

done <names.csv 
+0

この問題は、各ファイルの場所を知るのが難しいことです。パスは不明です。 – frosty

1

(コメント内の質問が明確になった後に回答を書き換えます)。

最初の解決策は、CSVにベース名だけでなくパス全体が含まれている場合にのみ機能します。それを繰り返し、各ファイルを見つけて名前を変更する必要があります。

sed -r 's/, ?/\t/' names.csv | while IFS=$'\t' read orig new; do 
    find $DIR -type f -name "$orig" | while read path; do 
     dirname=`dirname "$path"` 
     target_path="$dirname/$new" 
     if [[ ! -f "$target_path"]]; then 
     mv -v -- "$path" "$target_path" 
     else 
     echo "Could not rename '$path' to '$target_path'. Target file exists" >&2 
     fi 
    done 
done 

$DIRを一番上のディレクトリに置き換えます。注意各基本名は、異なるディレクトリにあるいくつかのファイルに対応していると仮定します。そのため、私はfindの出力を反復します。

+0

私はあなたの解決策を試しました。問題は自分のcsvがルートフォルダに存在し、ファイルはそのルートフォルダのどこにでも存在する可能性があるということです。ですから、私はROW-Nからファイルを掘る方法を見つける必要があります:COLUMN-1、それをROW-N:COLUMN-1に名前を変更します。 私は理想的にはかなり大きなcsvを解析できるはずです。ファイル(各行の最初の列)がどこにあるかを見つける(find、locate、grep?); (列2の同じ行の値に基づいて)名前を変更します。 これを理解する方法については本当に迷っています。 – frosty

+1

展開から二重引用符を削除することは、解決する方法ではなく、むしろ少しだけ修正する方法です。そのようなコードは適切に維持することができず、移植可能で危険ではありません。別々のソリューションを提供することによって2つの問題を処理する代わりに、両方を同時に処理します。堅牢なコードを作成します。また、 'mv" $ orig "" $ new "を' mv - "$ orig" "$ new" 'に変更して、オプションのようなファイル名(例えば' -m MODE') 'mv'の動作を変更することができます。さらに - [猫の無駄使い](http://porkmail.org/era/unix/award.html)。 –

+0

@frostyあなたの問題が正しいことを理解しているかどうか教えてください。 CSVファイルには、元のベース名とターゲットのベース名に関する情報のみが含まれています。タスクは、ベースネームでファイルを見つけて、ディレクトリ名を変更し、ディレクトリ名を変更することではありません。 –

関連する問題