Klasördeki her 4. dosyayı kopyalama


15

Bir klasörde birçok dosyam var 00802_Bla_Aquarium_XXXXX.jpg. Şimdi her 4. dosyayı bir alt klasöre kopyalamam gerekiyor selected/.

00802_Bla_Aquarium_00020.jpg <= this one
00802_Bla_Aquarium_00021.jpg
00802_Bla_Aquarium_00022.jpg
00802_Bla_Aquarium_00023.jpg
00802_Bla_Aquarium_00024.jpg <= this one
00802_Bla_Aquarium_00025.jpg
00802_Bla_Aquarium_00026.jpg
00802_Bla_Aquarium_00027.jpg
00802_Bla_Aquarium_00028.jpg <= this one
00802_Bla_Aquarium_00029.jpg

Bunu nasıl yaparım?


Bazı çıktılarda superuser.com/q/396536/87552 çözümlerini beğenebilirsiniz ls. Ayrıca her ikinci satırı soran stackoverflow.com/q/4553751/789593 adresine bakın .
NN

Numaralandırılmışlarsa ve son numarayı biliyorsanız, bir varyasyon düşünebilirsinizfor n in $(seq -w 20 4 200); do cp "00802_..._00${n}" ...; done
Ulrich Schwarz

Yanıtlar:


12

Zsh ile şunları yapabilirsiniz:

n=0; cp 00802_Bla_Aquarium_?????.jpg(^e:'((n++%4))':) /some/place

POSIXly, aynı fikir, biraz daha ayrıntılı:

# put the file list in the positional parameters ($1, $2...).
# the files are sorted in alphanumeric order by the shell globbing
set -- 00802_Bla_Aquarium_?????.jpg

n=0
# loop through the files, increasing a counter at each iteration.
for i do
  # every 4th iteration, append the current file to the end of the list
  [ "$(($n % 4))" -eq 0 ] && set -- "$@" "$i"

  # and pop the current file from the head of the list
  shift
  n=$(($n + 1))
done

# now "$@" contains the files that have been appended.
cp -- "$@" /some/place

Bu dosya adları boş veya joker karakter içermediğinden şunları da yapabilirsiniz:

cp $(printf '%s\n' 00802_Bla_Aquarium_?????.jpg | awk 'NR%4 == 1') /some/place

Lütfen posix kodunda da yorum yapabilir misiniz
Rahul Patil

@ChrisDown, for i dostandart ve aslında daha taşınabilir for i; dove konumsal parametreler üzerinde döngü kanonik yoludur.
Stéphane Chazelas

7

Bash, komik bir olasılık, burada oldukça iyi çalışacak:

cp 00802_Bla_Aquarium_*{00..99..4}.jpg selected

Bu kesinlikle en kısa ve en verimli cevaptır: alt kabuk yok, döngü yok, boru yok, awkharici işlem yok; sadece bir çatal cp(yine de kaçınamazsınız) ve bir bash brace genişleme ve glob (kaç dosya olduğunu bildiğiniz için tamamen kurtulabilirsiniz).


4
… Ve 2 varsayım: dosyalar sürekli olarak numaralandırılır ve ilki 4 ile bölünebilir.
manatwork

@manatwork ilk 4'e bölünemezse sorun yok: örneğin, cp 00802_Bla_Aquarium_*{03..99..4}.jpg selectedisterseniz 3 mod 4. (100'ün 4'e bölünebileceği harika gerçeğini kullanıyorum). Şimdi, sürekli numaralandırılmış dosyalar hakkında, diğer tüm yanıtlar aynı kabul edilir.
gniourf_gniourf

Başka hangi cevaplar sürekli numaralandırmayı varsayar? Sadece Ulrich Schwarz'ın yorumunu buldum ve böyle bir cevap bulamadım .
manatwork

5

Sadece bash ile şunları yapabilirsiniz:

n=0
for file in ./*.jpg; do
   test $n -eq 0 && cp "$file" selected/
   n=$((n+1))
   n=$((n%4))
done

Desen ./*.jpg, bash adamının belirttiği şekilde alfabetik olarak sıralanmış bir dosya adları listesiyle değiştirilecektir, bu nedenle amacınıza uymalıdır.


Bash olarak, içerdeki üç satır fordöngü sadece bu hat ile değiştirilebilir: (((++n)%4)) || cp "$file" selected/. ;-). Sorun olsa da gerçekten verimli olmayan her dosya cpiçin çatal üzerinde olmasıdır.
gniourf_gniourf

1

Eğer varsa rubyyüklü aşağıdaki tek astar kullanabilirsiniz. Seçilen dizinin var olduğunu varsaydığını unutmayın.

ruby -rfileutils -e 'files = Dir.glob("*.jpg").each_slice(4) { |file| FileUtils.cp(file.first, "selected/" + file.first) }'

Geçerli dizinde .jpg uzantılı tüm dosyaların bir listesini alır ve dört öğenin listelerine dilimler ve bu tür listelerden ilk öğeyi geçerli dizinde seçilen dizine kopyalar.


1

Dosya adlarınızda yeni satırlar olmayacağını biliyorsanız şunları kullanabilirsiniz:

find . -maxdepth 1 -name "*.jpg" | sort | while IFS= read -r file; do
  cp "$file" selected/
  IFS= read -r; IFS= read -r; IFS= read -r
done

@Gilles: düzenleme için teşekkürler. Gerek duymadıklarını belirtmek istediğim için 3 değişkenindeki dosya değişkenini kaldırdım.
jfg956

1

Bir GUI dosya yöneticisi kullanabilir ve her 5 dosya bir satırı kaplayana kadar pencerenin kenarlığını yeniden boyutlandırabilir ve ardından ilk sütunu seçmek için fareyi kullanabilirsiniz ...


-1

@NN'nin belirttiği gibi her saniyeyi kopyalamak için bir çözüm sunan stackoverflow.com/q/4553751/789593'e bakıldığında, çok basit bir çözüm:

  • İlk dosyayı başlangıç ​​klasöründen kaldırın
  • Her saniyede bir başlangıç ​​klasöründen bir ara klasöre kopyalayın
  • Her bir ikinciyi ara klasörden son klasöre kopyalayın
  • İlk dosyayı el ile ekleyin

Ekstra bir kopya adım biti gerektirdiğinden çok verimli olmayabilir, yapılması çok kolay olmalıdır.

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.