Birden çok dosyayı joker karakterle nasıl kopyalarım?


42

İçinde ABC olan bir sürü dosya bulunan bir klasörüm var. * (Kabaca 100 tane dosya var). Hepsini DEF ile başlayan isimlerle yeni dosyalara kopyalamak istiyorum. *

Bu yüzden istiyorum

ABC.Page1
ABC.Page2
ABC.Topic12
...etc

kopyalandı

DEF.Page1
DEF.Page2
DEF.Topic12
...etc

Bunu bir toplu komutla (BASH veya benzeri) yapmanın en basit yolu nedir? Sed veya awk veya xargs içeren bir şey düşünüyorum, ancak sözdizimini bulmakta zorluk çekiyorum. Bir Python betiği yazabilirim, ancak muhtemelen karmaşık olmayan bir komut satırı çözümü olduğunu düşünüyorum.


Saygın bir mcdosya yöneticisi, bu tür toplu adlar için en kapsamlı desteğe sahiptir.
oakad

@Oakad tarda bahar tavuğu değil. Örnek olarak cevabımı gör.
mikeserv

Yanıtlar:


41

Bash böyle bir şey hakkında nasıl:

for file in ABC.*; do cp "$file" "${file/ABC/DEF}";done

cp komutunun önüne eko koyarak test edebilirsiniz:

for file in ABC.*; do echo cp "$file" "${file/ABC/DEF}";done

mükemmel. hayal ettiğimden bile daha basit.
Ahtapot,

Çoğu durumda yeterince iyi olacak ancak yankı ile kontrol etmek burada çok önemlidir. Bunu asla bir komut dosyasında yapma . Daha fazla bilgi için bash tuzaklar
pawel7318

@ pawel7318, verdiğiniz bağlantı, mükemmel tavsiyeler sunarken, yukarıda verilen komuta uygulanmıyor gibi görünüyor. Ben bu komutla gördüğüm tek kenar durumlar şunlardır: (1) hedef dosya zaten var olmadığını kontrol etmez , ne de hedef dosya zaten bir şekilde varsa dizinine (dosyayı kopyalamak hangi içine bugünkü adını koruyarak dizininde), ve (2) küre genişletme işleminin tek bir komut satırına sığamayacağı kadar çok dosya varsa.
Joker,

1
Bunu anlıyorum: cp /usr/local/lib/libboost* /usr/local/lib/libboost*yankı kontrolü ile.
Tomáš Zato

8

Bunu çok sayıda dosyayla verimli bir şekilde yapmak cpiçin, her biri için farklı bir işlem başlatmaktan kaçınmak daha iyidir . Bir yol kopyalamak ve sonra bunları kullanarak yeniden adlandırmak olacaktır prename( renameDebian tabanlı dağıtımlarda varsayılan olarak buna bağlanmıştır). Bunu ve Linux'u kullanmak mktemp:

tmp=$(mktemp -d --tmpdir=.)
cp ABC.* "$tmp"
prename "s:$tmp/ABC:DEF:" "$tmp/"*
rmdir "$tmp"

Güncelleme

Aslında paxburaya gitmek için daha iyi bir yol olabilir:

pax -rws '/^ABC/DEF/' ABC.* .

Ne yazık ki, paxhem POSIX hem de Linux Standard Base olmasına rağmen , birkaç dağıtım şu anda varsayılan olarak içermektedir.


kaçmaktan kaçınmak için ayırıcı olarak: düğmesine dokunarak hoş dokunun.
Clayton Stanley

5

tar Bunu gerçekten hızlı bir şekilde yapacağım.

ÖLÇEK

İlk önce 2 dizin ve 10 dosya oluşturdum:

% mkdir test1 test2 ; cd test1
% for n in `seq 1 10` ; do touch ABC.file$n ; done
% ls

> ABC.file1   ABC.file2  ABC.file4  ABC.file6  ABC.file8
> ABC.file10  ABC.file3  ABC.file5  ABC.file7  ABC.file9

Sonra onları kopyaladım:

% tar -cf - ./* |\ 
    tar -C../test2 --transform='s/ABC/DEF/' -xf -
% ls ../test2

> DEF.file1   DEF.file2  DEF.file4  DEF.file6  DEF.file8
> DEF.file10  DEF.file3  DEF.file5  DEF.file7  DEF.file9

DÖNÜŞÜMÜ

Bu yüzden GNU for adının yeniden adlandırılmasını tarkabul edecektir sed --transform=EXPRESSION. Bu sadece dosyaların bazılarını yeniden adlandırabilir. Örneğin:

% tar -cf - ./* |\ 
    tar -C../test2 --transform='s/ABC\(.*[0-5]\)/DEF\1/' -xf -
% ls ../test2

> ABC.file6  ABC.file8  DEF.file1   DEF.file2  DEF.file4
> ABC.file7  ABC.file9  DEF.file10  DEF.file3  DEF.file5

Yani bu bir avantaj.

AKIŞ

Ayrıca bunun yalnızca iki tarişlem olduğunu ve dosya sayınızdan bağımsız olarak değişmeyeceğini de göz önünde bulundurun .

tar | tar

taristediğiniz gibi optimize edilmiştir. Bu asla sorun argüman sayımına veya kaçınılmaz çocuk işlemlerine sahip olmayacak. Bu sadece A> B yapıldı.

ARGÜMANLAR

tarBuradaki iki işlemim arasında 7 farklı argüman kullanıyorum . En önemlisi önce burada listelenmiştir:

-stdout / stdin - bu , bir arşiv oluşturup oluşturmadığına veya çıkarıp almadığına bağlı olarak tar, girdi veya çıktılarını stdin/stdoutdoğru şekilde yorumlayacağı ya da çıkacağı bilgisini verir.

-ccreate - bu tararşivi oluşturmayı söyler . Bir sonraki tartışma tarbekliyor ...

-fdosya - bunun bir teyp aygıtı yerine nesneyle ya da taronunla çalışacağını belirtiriz file. Ve üzerinde çalışacağı dosya, yukarıda belirtildiği gibi stdin/stdout- başka bir deyişle, bizim |pipe.

./*tüm $ PWD / files - arşiv argümanının önce gelmesi dışında burada açıklamak için fazla bir şey yok, o -zaman ./*.

... ve diğer tarafında |pipe...

-Cdizin değiştir - bu tar, başka bir işlem yapmadan önce belirttiğim dizine geçmesi gerektiğini, bu yüzden etkin bir şekilde bu dizinin cd ../test2çıkarılmasından hemen önce etkin olduğunu gösterir .

--transform='s/ed/EXPR/'- Daha önce de belirtildiği gibi, bu yeniden adlandırma yaptı. Ancak dokümanlar herhangi bir sedifade alabileceğini ya da ifade edebileceğini belirtir //flag.

-xözü - sonra tarhedef dizine değişiklikler ve bizim adlandırma talimat aldığı bunun talimat gelen bugünkü dizine tüm dosyaları ayıklanması başlamak için -f - |pipearşiv dosyası. Gizem yok.


1
İşte paxbu sorunun çözümü. Cevabımı ekleyecektim, ama burada daha uygun olduğunu düşünüyorum -pax -rws '/^ABC/DEF/' ABC.* .
Graeme

@Graeme - woah - bu daha iyi! Dostum, aynı zamanda inci ismini de mahvediyor! Bunu cevabınıza paxyazmalısınız - POSIX belirtilmiş - bu nedenle pax.
mikeserv

paxPOSIX olabilir, ancak ne yazık ki varsayılan olarak nadiren kurulur.
Graeme

4

Daha az standart bir araç kullanmanın sakıncası yoksa, bu tür işler için yazılmış olan mmv'yi (toplu taşıma) kullanmanızı öneririz . Paketin bir mcpparçası olan (toplu kopya) kullanarak

mcp "ABC.*" "DEF.#1"

İndirme paketlerini bulmak tam olarak kolay değil. Evde derlemek için mevcut Debian paketi (Arch'ın AUR'da da kullandığı) burada bulunabilir .


kutudan dışarı ubuntu 15.10 üzerine kurar,apt-get install mmv
Thufir

2

Zsh içine, aşağıdaki satırları içine koyun .zshrc:

autoload -U zmv
alias zmv='noglob zmv'
alias zcp='zmv -C'
alias zln='zmv -L'

Sonra komut satırında çalıştırabilirsiniz

zcp 'ABC(.*)' 'DEF$1'

ya da sadece

zcp -W ABC.* DEF.*

Başka bir kabukta, zsh kurulu olduğu sürece:

zsh -c 'autoload zmv; noglob zmv -CW ABC.* DEF.*'

1

Bunu yapabilirsin:

for i in ABC.*; do cp {ABC,DEF}."${i#*.}"; done

Belki görmediğim bir şey var, ama nasıl birden fazla hedef belirleyebilirim? Her birini almak için for döngüsünü kullanıyorum. Kodu önceden test ettim ve beklendiği gibi çalıştı, bu yüzden açıklamanızı takdir ediyorum.
Sara Fauzia

Bu benim kötü, cevabını yanlış okudum. :-)
Chris Down

Ucu nasıl okuyayım "${i#*.}"?
dumbledad

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.