あるフォルダーから別のフォルダーに複数の特定のファイルをコピーする


133

写真(数千)の大きなフォルダーがあり、正確なファイル名で別のフォルダーにコピーする必要があるファイルの長いリストがあります。このフォルダーからいくつかの特定のファイルを名前で選択し、個別にコピーせずにターミナルを使用して別のフォルダーにコピーする方法があるかどうかを知りたいですか?


Fyi、特定のフォルダーをコピーするcp -rp /copying/from/{folder1/,folder2/,folder3/} path/to/folderpは、を使用します。ここで、フォルダーの許可をコピーします。
ラクティムビスワス

回答:


179

コマンドラインから一度に複数のファイルをコピーするだけです

これを実現する方法はいくつかあります。私が見た最も簡単な方法は、以下を使用することです。

cp /home/usr/dir/{file1,file2,file3,file4} /home/usr/destination/

構文では、cpコマンドの後に、目的のファイルが置かれているディレクトリへのパスを続けて使用し、コピーするすべてのファイルを角かっこで囲み、カンマで区切ります。

ファイル間にスペースがないことに注意してください。コマンドの最後の部分は/home/usr/destination/、ファイルのコピー先のディレクトリです。

または、すべてのファイルのプレフィックスが同じで、末尾が異なる場合は、次のようにすることができます。

cp /home/usr/dir/file{1..4} ./

file1、file2、file3、およびfile4がコピーされる場所。

あなたが質問をどのように表現したかから、これがあなたが探しているものであると信じていますが、ファイルのリストから読み取り、それらをすべて特定のディレクトリにコピーするコマンドを探しているかもしれません。その場合はお知らせください。回答を編集します。

Pythonで重複を処理する

それで、私は仕事を成し遂げるべきだと思う小さなpythonスクリプトを書きました。しかし、あなたがPythonにどれだけ精通しているかわからない(まったく精通している場合)ので、このスクリプトをできる限り使用する方法を説明してみて、必要なだけ質問してください。

import os,sys,shutil
### copies a list of files from source. handles duplicates.
def rename(file_name, dst, num=1):
    #splits file name to add number distinction
    (file_prefix, exstension) = os.path.splitext(file_name)
    renamed = "%s(%d)%s" % (file_prefix,num,exstension)

    #checks if renamed file exists. Renames file if it does exist.
    if os.path.exists(dst + renamed):
        return rename(file_name, dst, num + 1)
    else:
        return renamed

def copy_files(src,dst,file_list):
    for files in file_list:
        src_file_path = src + files
        dst_file_path = dst + files
        if os.path.exists(dst_file_path):
            new_file_name =  rename(files, dst)
            dst_file_path = dst + new_file_name

        print "Copying: " + dst_file_path
        try:
            shutil.copyfile(src_file_path,dst_file_path)
        except IOError:
            print src_file_path + " does not exist"
            raw_input("Please, press enter to continue.")

def read_file(file_name):
    f = open(file_name)
    #reads each line of file (f), strips out extra whitespace and 
    #returns list with each line of the file being an element of the list
    content = [x.strip() for x in f.readlines()]
    f.close()
    return content

src = sys.argv[1]
dst = sys.argv[2]
file_with_list = sys.argv[3]

copy_files(src,dst,read_file(file_with_list))

このスクリプトは、比較的簡単に使用できます。まず、上記のコードをプログラムgedit(Ubuntuにプリインストールする必要があります)またはその他のテキストエディターにコピーします。

それが完了したら、ファイルをホームディレクトリにmove.pyとして保存します(任意のディレクトリを指定できますが、説明を簡単にするために、ホームディレクトリを使用します)。ファイルが含まれるディレクトリをPATHに追加します。次にcd、ターミナルからホームディレクトリ(またはmove.pyを保存したディレクトリ)に移動し、次のコマンドを入力します。

python move.py /path/to/src/ /path/to/dst/ file.txt

これにより、ソースディレクトリから宛先ディレクトリにリストされているすべてのファイルが、pic(1).jpg、pic(2).jpgなどの形式で重複してコピーされます。 file.txtは、コピーしたいすべての画像をリストしたファイルで、各エントリは個別の行になっている必要があります。

このスクリプトがソースディレクトリに影響を与えることはありませんが、ソースおよび宛先ディレクトリへの正しいパスを入力するようにしてください。最悪の事態は、ファイルを間違ったディレクトリにコピーすることです。

ノート

  • このスクリプトは、元の画像がすべて同じディレクトリにあることを前提としています。サブディレクトリもチェックする場合は、スクリプトを変更する必要があります。
  • 誤ってファイル名を誤って入力した場合、スクリプトは
    「ファイルが存在しません」というエラーを吐き出し、「Enter」を押して続行するようプロンプトを表示し、スクリプトはリストの残りのコピーを続行します。
  • /ソース
    ディレクトリへのパスと宛先ディレクトリへのパスの両方の末尾を忘れないでください。そうしないと、スクリプトがエラーを吐き出します。

私の問題のほとんどを解決してくれてありがとう、しかし、いくつかのファイルがリストに2回以上表示されます。(はい、私がやっていることのために複製が必要です。)
ピクトが多すぎる人

異なるサブフォルダーからの重複ですか、またはfile.jpgやfile(1).jpgのようなラベルが付けられていますか?それ以外の場合、同一のファイルがどのようにあるかわかりません。あなたの質問にいくらか答えるために、あなたはあなたのために自動的に重複の名前を変更するシンプルなライナーを見つけることができるとは思わない。そのような機能を実現するには、bashまたは他の種類のスクリプトを作成する必要があると思います。ただし、かなりおかしな1行のコマンドを見たので、Linuxウィザードが表示されて答えが返される場合があります。
ブライアン

元々各ファイルは1つしかありませんが、ファイルの名前がリストに2回以上あります。新しいフォルダーにファイルを配置しようとして、その名前のファイルが既に存在する場合、多かれ少なかれそれを行うために必要なことは、ファイル名の最後に(2)程度を追加する必要があります置きます。
ピクトが多すぎる人

コピーするファイルのリストにスペースがないことに関する部分を強調することをお勧めします。ファイル{foo、bar、..}の間にもスペースがある場合、コマンドは機能しません。
フランクサンズ

さらにショートカットを求める方のために、あなたはファイル、すなわちの絶対パスのためで立つようにコマンド置換を使用することができcp $(pwd)/{file1,file2} /path/to/dst/たりcp $(pwd)/{file1,file2} $(pwd)/{renamed1,renamed2}、など
baelx

49

おそらく、あなたの質問の詳細が欠けていますが、与えられた答えは過剰に思えます。スクリプトではなくコマンドラインソリューションが必要な場合は、次のようにします。

cd /path/to/src/
cp -t /path/to/dst/ file1 file2 file3 ...

この方法で行うことの良い点は、ファイル名をTabキーで補完できることです。


5
これはMacOSのシエラに「不正なオプションの--t」を返す
geoyws

すばらしい答え、はるかに簡単。@geoywsたぶん、AppleのバージョンにはないPOSIXやGNUのものでしょう。Debian LinuxまたはWindowsでMSYS2を使用するとうまく動作します。
underscore_d

素敵な提案!Arch Linuxで働いていました。
エドゥルイス

brew install coreutilsその後、通常のgnuのものにgプレフィックスを付けて取得できます。だからgcp -t ....
T.Chmelevskij

Mac OSはのBSDバージョンを使用しcp、特にOpenBSDFreeBSDもそのオプションがないため、はい-これはGNU cp 固有です。POSIX標準でも指定されていません。これはUbuntuの特定のサイトがあるので、これは許容可能であるが、OSの間のスクリプトを移植するためには、POSIX標準に固執する方が良いでしょう
Sergiy Kolodyazhnyy

7

これが純粋なbashソリューションです。入力ファイルからファイル名(1行に1つ)を読み取り、それぞれをコピーして、重複の名前を変更します。

#!/usr/bin/env bash

## The destination folder where your files will
## be copied to.
dest="bar";

## For each file path in your input file
while read path; do 
    ## $target is the name of the file, removing the path. 
    ## For example, given /foo/bar.txt, the $target will be bar.txt.
    target=$(basename "$path"); 
    ## Counter for duplicate files
    c=""; 
    ## Since $c is empty, this will check if the
    ## file exists in target.
    while [[ -e "$dest"/"$target"$c ]]; do
        echo "$target exists"; 
        ## If the target exists, add 1 to the value of $c
        ## and check if a file called $target$c (for example, bar.txt1)
        ## exists. This loop will continue until $c has a value
        ## such that there is no file called $target$c in the directory.
        let c++; 
        target="$target"$c; 
    done; 
    ## We now have everything we need, so lets copy.
    cp "$path" "$dest"/"$target"; 
done

このスクリプトをのフォルダーに保存し、$PATHパスのリストを入力として呼び出します。

auto_copy.sh < file_paths.txt

ターミナルからコマンドとして全体を実行することもできます。

while read path; do 
   target=$(basename "$path"); 
   c=""; 
   while [[ -e bar/"$target"$c ]]; do 
    echo "$target exists"; 
    let c++; 
    target="$target"$c; 
   done; 
   cp "$file" bar/"$target"; 
done < file_names;

1

質問の説明によると、私の理解は次のとおりです。

  • ファイルのリスト、おそらくテキストファイルがあります input.txt
  • リストにはファイル名のみが含まれます
  • これらのファイル名がある特定のディレクトリがあります。

したがって、次のコマンドを使用できます。

xargs -I % --arg-file=input.txt cp  /path/to/origin_dir/%  /path/to/destination

説明:

  • -I % コマンド内で使用される現在処理されているファイルのシンボルを指定します
  • --arg-file=input.txt コマンドの引数を取ることを指定します input.txt
  • cp /path/to/origin_dir/% /path/to/destination/現在処理されているファイルの名前と名前に置き換えてcpコマンドを実行します。/path/to/origin_dir/%/path/to/origin_dir/

実際の例:

$ cat input.txt
file2.txt
file1.txt
file3.txt
$ ls ./docs
file1.txt  file2.txt  file3.txt
$ xargs -I % --arg-file=input.txt cp ./docs/% ./docs_destination/
$ ls ./docs_destination/
file1.txt  file2.txt  file3.txt
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.