Копирование нескольких определенных файлов из одной папки в другую

83

У меня есть большая папка с картинками (тысячи), и у меня есть длинный список файлов по точному имени файла, который мне нужно скопировать в другую папку. Я хочу знать, есть ли способ выбрать несколько определенных файлов из этой папки по имени и скопировать их в другую папку, используя терминал, без копирования их отдельно?

    
задан Someone with far too many pict 01.08.2013 в 07:44
источник

3 ответа

113

Просто скопируйте сразу несколько файлов из командной строки

Есть несколько способов добиться этого. Самый легкий, который я видел, это использовать следующее.

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

Синтаксис использует команду cp, за которой следует путь к каталогу, в котором находятся нужные файлы, со всеми файлами, которые вы хотите скопировать, заключенными в скобки и разделенными запятыми.

Убедитесь, что между файлами нет пробелов. Последняя часть команды /home/usr/destination/ - это каталог, в который вы хотите скопировать файлы.

, или если все файлы имеют один и тот же префикс, но разные окончания, вы можете сделать что-то вроде этого:

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

Если будут скопированы файлы1, 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 in), с терминала и введите следующую команду:

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

Это должно скопировать все файлы, перечисленные в исходном каталоге, в целевой каталог с дубликатами, которые принимают формат pic (1) .jpg, pic (2) .jpg и так далее. file.txt должен быть файл, в котором перечислены все изображения, которые вы хотите скопировать, с каждой записью в отдельной строке.

Никоим образом этот сценарий не влияет на исходный каталог, но просто убедитесь, что вы ввели правильные пути в каталог источника и назначения, а самое худшее, что может произойти, - это скопировать файлы в неправильный каталог.

Примечания

  • Этот сценарий предполагает, что все исходные изображения находятся в одном и том же каталог. Если вы хотите, чтобы он также проверял вспомогательные каталоги, скрипт необходимо будет изменить.
  • Если вы случайно ошиблись в имени файла, скрипт выплюнет ошибку
    «файл не существует» и предложит вам «нажать Enter», чтобы продолжить, и скрипт продолжит копирование остальной части списка.
  • Не забывайте конечный / как по пути к источнику
    каталог и путь к целевому каталогу. В противном случае скрипт вернет вам ошибку.

Надеюсь, это поможет!     

ответ дан Bryan 01.08.2013 в 08:04
21

Возможно, мне не хватает детали вашего вопроса, но приведенные ответы кажутся чрезмерными. Если вам требуется решение командной строки, а не сценарий, почему бы и нет:

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

Самое приятное в том, что вы делаете это так, чтобы вы могли заполнить имена файлов

    
ответ дан Ross Allen 25.08.2016 в 19:48
6

Вот чистое решение bash. Он будет читать имена файлов из входного файла (по одному на строку) и копировать их, переименовывать дубликаты.

#!/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;
    
ответ дан terdon 01.08.2013 в 17:24