2016-05-24 4 views
-1

これを必要とする可能性のある他の人を支援するためにここに配置すると思いました。UNIX:同じ名前のすべてのファイルを別のディレクトリにコピーしてコピーする方法

私は、サーバー上の500の異なる場所にあるspreadsheet.csvという名前のファイルを持っていました。一連の試行錯誤の後、私はこのファイルのすべてのインスタンスをコピーし、名前を変えて(名前を変えて)名前を変えて別のフォルダにコピーするようにこの解決策を打ち出しました。

これが誰かを助けることを願っています!シンプルなbashfor-loopこの達成できる

COUNTER=0; 
for f in $(find folder/ -name 'spreadsheet.csv'); 
do 
    cp -v $f /new/location/spreadsheet$COUNTER.csv; 
    COUNTER=$[$COUNTER+1]; 
done 
+4

このウェブサイトのフォーマットに従ってください。質問に問題を提起し、以下の答えを記入してください。 – chepner

+0

Bash '$ [...算術...]'表記は、 '$((...算術...))'または '((...算術...))'の代わりに非難されることに注意してください - [算術拡張](https:// www.gnu.org/software/bash/manual/bash.html#Arithmetic-Expansion)。単一の大括弧で囲まれた '$ [...]'はこれ以上文書化されていません。 –

答えて

1

: -

COUNTER="0" 
fileName="spreadsheet.csv" 
for file in $(find folder/ -name "$fileName" -type f -printf '%P\n'); 
do 
    sourcePath=$(dirname $(readlink -f "$file")) 
    cp -v $sourcePath/$fileName /new/location/"$fileName$COUNTER" 
    COUNTER=$((COUNTER+1)) 
done 

を、スクリプトの重要な部分は、私がreadlinkdirnameを通じて実現していた、各ファイルのソースパスを取得しています。その説明について詳しくは、manページを参照してください。

例: - 少なくとも1人のディレクトリ名にスペースや特殊文字がある場合

$ find . -name "spreadsheet.csv" -type f 
./foo/spreadsheet.csv 
./bar/spreadsheet.csv 
./woo/spreadsheet.csv 
./spreadsheet.csv 

$ ./script.sh 
`/home/dude/foo/spreadsheet.csv' -> `/new/location/spreadsheet.csv0' 
`/home/dude/bar/spreadsheet.csv' -> `/new/location/spreadsheet.csv1' 
`/home/dude/woo/spreadsheet.csv' -> `/new/location/spreadsheet.csv2' 
`/home/dude/spreadsheet.csv' -> `/new/location/spreadsheet.csv3' 
+0

ディレクトリ名のスペース文字やその他の特殊文字は、これを破ることになります: 'mkdir foo \ bar; touch foo \ bar/speadsheet.csv' –

+0

私はシンボリックリンクをコーディングする特別なケースについて困惑しています。それはなぜ必要なのですか? 'cp'でシンボリックリンクにアクセスすると、シンボリックリンクの最後にファイルのコピーを作成し、シンボリックリンクの情報はコピーしません。だから、 'readlink'と' dirname'を使うことは、過剰なもののように思えます。システムは自動的にそれを処理します( 'cp -v" $ file "" $ new_location/$ fileName $ COUNTER.csv "は'.csv'拡張の前に番号が来る必要があるので' fileheet'を単に '' spreadsheet''に変更するだけです)。 –

0

スクリプトは、破るしようとしています。

Inianも正しく約symlinksです。

のみ、通常のファイルが検索され、安全で標準溶液の下にあります:追加のNULLで見つかったファイルの

find folder/ -type f -name 'spreadsheet.csv' -printf "%p\0" | xargs -0 sh -c ' 
    newlocdir=/new/location; 
    COUNTER=$(ls -1 "${newlocdir}"/spreadsheet*.csv 2>/dev/null | awk "END {print NR}") ; 
    for f ; do 
    cp -v "${f}" "${newlocdir}"/spreadsheet$COUNTER.csv; 
    COUNTER=$(($COUNTER+1)); 
    done' dummyarg0 

-printf "%p\0"プリントのパス名を。

xargs -0は、見つかったファイルを読み取り、エントリ間のセパレータとしてNULL文字を考慮することができます。

| awk "END {print NR}"は、パイプラインから読み取る行数を表示します。

COUNTER=$(ls -1 "${newlocdir}"/spreadsheet*.csv 2>/dev/null | awk "END {print NR}")は、すでに新しい場所に存在するファイルの番号をCOUNTER変数に格納します。

for f ; doは、位置パラメータを読み取ります。ファイル名はxargsによって提供されます。

sh -c ' .... ' dummyarg0shは、提供されたコマンドを実行します。 dummyarg0は、必須の最初のパラメータです。 shは、特殊パラメータ0の値をdummyarg0(未使用)に設定します。

テスト:

$ find folder/ 
folder/ 
folder/dir2 
folder/dir2/spreadsheet.csv 
folder/foo bar 
folder/foo bar/spreadsheet.csv 
folder/spreadsheet.csv 
folder/tr"uc 
folder/tr"uc/spreadsheet.csv 
folder/fo'o 
folder/fo'o/spreadsheet.csv 
folder/dir1 
folder/dir1/spreadsheet.csv 
$ find folder/ -type f -name 'spreadsheet.csv' -printf "%p\0" | xargs -0 sh -c ' 
    newlocdir=.; 
    COUNTER=$(ls -1 "${newlocdir}"/spreadsheet*.csv 2>/dev/null | awk "END {print NR}") ; 
    for f ; do 
    cp -v "${f}" "${newlocdir}"/spreadsheet$COUNTER.csv; 
    COUNTER=$(($COUNTER+1)); 
    done' dummyarg0 
`folder/dir2/spreadsheet.csv' -> `./spreadsheet0.csv' 
`folder/foo bar/spreadsheet.csv' -> `./spreadsheet1.csv' 
`folder/spreadsheet.csv' -> `./spreadsheet2.csv' 
`folder/tr"uc/spreadsheet.csv' -> `./spreadsheet3.csv' 
`folder/fo\'o/spreadsheet.csv' -> `./spreadsheet4.csv' 
`folder/dir1/spreadsheet.csv' -> `./spreadsheet5.csv' 
関連する問題