2012-03-31 8 views
0

find -execコマンドを使用して、すべてのファイルを特定のフォルダにコピーできます。 しかし、私がする必要があるのは、保存されているフォルダと共に、指定されたパス内のすべてのファイルを検索してコピーすることです。そう....ファイルを最後のフォルダと共にコピーする

/path/to/file/is/abc.txt 
/another/file/is/here/xyz.txt 

は、私は次のフォルダへのパスと一緒にこれらの2つのファイルをコピーする必要があります。

/mysqlの/データ/

新しいファイル構造は次のようになります。 ..

/mysql/data/is/abc.txt 
/mysql/data/here/xyz.txt 

これは、重複するファイル名の上書きを避けるために行われます。最後のフォルダ名は一意になりますが、ファイル名は同じでもかまいません。

これを行うにはどのような方法が最適ですか?

答えて

3

をここで簡潔ですかなり長い説明のあるスクリプト*が付いています。それはdirnameユーティリティにすべてを削除し、パスから最後のスラッシュ(/)を含む

  • 仕組み

    for oldpath in $your_file_list; do 
        mv ${oldpath} /mysql/data${oldpath##$(dirname $(dirname $oldpath))} 
    done 
    

    。これを2回呼び出すと、2行目から最後のスラッシュまでのすべてが削除されます。

  • イディオムは、パラメータwith paramscommandを実行し、出力を返します。

  • イディオム${var##prefix}は、変数varの内容をprefixで削除して返します。

ステップバイステップ解析

oldpath/path/to/file/is/abc.txtある場合:

  • dirname $oldpath/path/to/file/is
  • dirname $(dirname $oldpath)ある/path/to/file
  • ${oldpath##$(dirname $(dirname $oldpath))}がであります

これは、元のパスのうち、新しいパスに追加される部分です。


*エレガントADJ。)ソフトウェア:説明長い実装自体よりもアルゴリズムを実装するソフトウェア。

1

このソリューションをスクリプト/プログラムする必要があります。

クイックPythonの例は次のとおりです。

import os 
import shutils 
src_root = '/path/to/walk/' 
dst_root = '/mysql/data/' 
for root,dirs,files in os.walk(src_root): 
    for file in files: 
     dst_path = os.path.split(root)[1] 
     dst_path = os.path.join(dst_root, dst_path) 
     os.makedirs(dst_path) 
     src = os.path.join(root,i file) 
     dst = os.path.join(dst_path, file) 
     shutils.copyfile(srd, dst) 
1

これはあなたのために働くかもしれない:

a=/mysql/data 
sed 's|.*\(/[^/]*/[^/]*\)|mv -v & '"$a"'\1|' file 
mv -v /path/to/file/is/abc.txt /mysql/data/is/abc.txt 
mv -v /another/file/is/here/xyz.txt /mysql/data/here/xyz.txt 

研究を出力し、すべてOKが、その後、実行した場合:

sed 's|.*\(/[^/]*/[^/]*\)|mv -v & '"$a"'\1|' file | bash 
0

最初にファイルをコピーする場合は、そのディレクトリを作成する必要があります。あなたはsingle findコマンドを使ってそれを行うことができますが、私はこの解決法の効率についてよく分かりません。

#!/bin/bash 
# $1 - destination 

find $1 -type f -exec bash -c ' 
    dest="$2";       # $2 is second argument passed to the script 
    dir=$(basename $(dirname $1));   
    mkdir $dest/$dir 2>/dev/null;   
    cp $1 "$dest/$dir/";     
' -- {} $2 \;       # {} = $1 in bash '..' and $2=$2 

用法:./copy copy_from copy_to

編集: 良く見える:

#!/bin/bash 

dest=$2 
from=$1 

# copy_file from dest 
copy_file() { 
dir=$(basename $(dirname $from)) 
mkdir $dest/$dir 
cp $from $dest/$dir 
} 

find $from -type f | while read file; do copy_file $file $dest; done 
関連する問題