Bir klasörden diğerine birden çok özel dosya kopyalama

97

Büyük bir resim klasörüne sahibim (binlerce) ve bir dosyaya, dosya adına göre başka bir klasöre kopyalamam gereken uzun bir liste var. Bu klasörden birkaç özel dosyayı seçebileceğim bir yol olup olmadığını öğrenmek istiyorum ve bunları tek tek kopyalıp terminali kullanarak başka bir klasöre kopyalayabilir miyim?

    
sordu Someone with far too many pict 01.08.2013 07:44

4 cevap

132

Komut satırından tek seferde birden çok dosyayı kopyalayın

Bunu başarabilmenizin birkaç yolu vardır. Gördüğüm en kolay, aşağıdakileri kullanmaktır.

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

Sözdizimi, cp komutunu kullanarak dizinin yolunu izler ve istenen dosyalar, kopyalanmış parantez içine kopyalamak ve virgülle ayırmak istediğiniz tüm dosyalarda bulunur.

Dosyalar arasında boşluk olmadığından emin olun. Komutun son kısmı, /home/usr/destination/ , dosyaları kopyalamak istediğiniz dizindir.

veya tüm dosyalar aynı öneki ancak farklı sonlara sahipse böyle bir şey yapabilirsiniz:

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

Dosya1, dosya2, dosya3 ve dosya4 kopyalanacak.

Soruyu nasıl düşündüğünüzden, aradığınız şeyin bu olduğuna inanıyorum ama aynı zamanda bir dosya listesinden okumak ve hepsini belirli bir dizine kopyalamak için bir komut aradığınız gibi geliyor. Bu durumda bana bildirin ve cevabımı düzenleyeceğim.

Python ile çift kopyalarla uğraşmak

Bu yüzden işi bitirmesi gerektiğine inandığım bir python senaryosu yazdım. Bununla birlikte, python'da ne kadar becerikli olduğunuzdan emin değilim (eğer okuyuculuysa) bu yüzden bu senaryoyu nasıl kullanacağımı en iyi şekilde açıklamaya çalışacağım ve ihtiyacınız olduğu kadar çok soru sormak istiyorum.

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))

Bu betiğin kullanımı nispeten basit olmalıdır. Öncelikle yukarıdaki kodu programın geditine (Ubuntu'da önceden yüklenmiş olmalıdır) veya başka bir metin editörüne kopyalayın.

Bu işlem tamamlandıktan sonra, dosyayı ana dizininizde move.py olarak kaydedin (herhangi bir dizin olabilir, ancak kolaylık sağlamak için yalnızca ana dizini kullanır) veya dizini dosyaya ekleyin. PATH'nizde bulunur. Sonra terminalden cd (ya da move.py in kaydettiğiniz her hangi bir dizin) dizininden co_de% yazıp aşağıdaki komutu yazın:

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

Bu, kaynak dizinden listelenen dosyaların tümünü, pic (1) .jpg, pic (2) .jpg vb. biçimlerini alarak çoğaltmalarıyla hedef dizine kopyalamalıdır. file.txt , her girişe kopyalamak istediğiniz tüm resimleri kendi ayrı satırında listeleyen bir dosya olmalıdır.

Bu komut dosyası kaynak dizini etkilemez, ancak kaynak ve hedef dizinin doğru yollarını girdiğinizden ve en kötüsü de dosyaların yanlış dizine kopyalandığından emin olun.

Notlar

  • Bu komut, orijinal resimlerin hepsinin aynı olduğunu varsayar dizin. Alt dizinleri de kontrol etmek istiyorsanız Değiştirilmesi gerekecek.
  • Yanlışlıkla bir dosya adını yanlış yazıyorsanız, betik hatayı çıkarır
    "dosya mevcut değil" ve devam etmek için "enter tuşuna" basmanızı ve komut dosyasının geri kalanını kopyalamaya devam etmesini isteyin.
  • Hem kaynak kaynağına hem de yoldaki / izini unutmayın. dizin ve hedef dizine giden yol. Aksi halde senaryo Bir hatayı size geri gönderecek.
verilen cevap Bryan 01.08.2013 08:04
26

Belki de sorunuzun bir detayını kaçırıyorum, ancak verilen cevaplar aşırı görünüyor. Komut satırı çözümü ve komut dosyası istemiyorsanız, neden olmasın:

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

Bu şekilde yapmanın en güzel yanı, dosya adlarını tamamlayabilmenizdir

    
verilen cevap Ross Allen 25.08.2016 19:48
6

İşte saf bir bash çözüm. Bir giriş dosyasından (satır başına bir tane) dosya isimlerini okuyacak ve her birini kopyalayacak, kopyaları yeniden adlandıracaktır.

#!/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

Bu komut dosyasını $PATH 'daki bir klasöre kaydedin ve giriş olarak yolların listesiyle arayın:

auto_copy.sh < file_paths.txt

Ayrıca, tüm şeyi terminalden bir komut olarak da çalıştırabilirsiniz:

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;
    
verilen cevap terdon 01.08.2013 17:24
0

Sorunun açıklamasına göre, benim anlayışım şudur:

  • bir dosya listesi, muhtemelen bir metin dosyası input.txt var
  • listede yalnızca dosya adları var
  • bu dosya adlarının bulunduğu belirli bir dizin var.

Böylece, aşağıdaki komutu kullanabilirsiniz:

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

Açıklama:

  • -I % , komutun içinde kullanılmak üzere şu anda işlenen dosyanın sembolünü belirtir
  • --arg-file=input.txt , input.txt 'den komut vermek için bağımsız değişkenler almayı belirtir
  • cp /path/to/origin_dir/% /path/to/destination/ , cp ile /path/to/origin_dir/% ve şu anda işlenmiş dosyanın adı ile /path/to/origin_dir/ komutunu gerçekleştirecektir.

Pratik örnek:

$ 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
    
verilen cevap Sergiy Kolodyazhnyy 26.05.2018 09:32

Etiketlerdeki diğer soruları oku