किसी फोल्डर में हर 4 वा फाइल को कॉपी कैसे करें


15

मेरे पास एक फ़ोल्डर में बहुत सारी फाइलें हैं, जैसे नाम 00802_Bla_Aquarium_XXXXX.jpg। अब मुझे हर चौथी फ़ाइल को एक सबफ़ोल्डर में कॉपी करने की आवश्यकता है , जिसमें कहा गया है 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

मैं यह कैसे करु?


आप कुछ आउटपुट पर superuser.com/q/396536/87552 के समाधानों की तरह करने में सक्षम हो सकते हैं ls। यह भी देखें stackoverflow.com/q/4553751/789593 जो हर दूसरी पंक्ति के बारे में पूछता है।
एनएन

यदि वे क्रमांकित हैं और आप अंतिम संख्या जानते हैं, तो आप भिन्नता पर विचार कर सकते हैंfor n in $(seq -w 20 4 200); do cp "00802_..._00${n}" ...; done
उलरिच श्वार्ज़

जवाबों:


12

Zsh के साथ, आप कर सकते हैं:

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

POSIXly, एक ही विचार, बस थोड़ा और अधिक क्रिया:

# 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

चूंकि उन फ़ाइलनामों में कोई रिक्त या वाइल्डकार्ड वर्ण नहीं है, आप यह भी कर सकते हैं:

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

क्या आप कृपया टिप्पणी को पॉज़िक्स कोड में भी डाल सकते हैं
राहुल पाटिल

@ क्रिसडाउन, for i doमानक और वास्तव में अधिक पोर्टेबल है for i; doऔर स्थितिगत मापदंडों पर लूप करने के लिए विहित तरीका है।
स्टीफन चेजेलस

7

बैश में, एक मज़ेदार संभावना, जो यहाँ अच्छी तरह से काम करेगी:

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

यह निश्चित रूप से सबसे छोटा और सबसे कुशल जवाब है: कोई उपधारा, कोई लूप, कोई पाइप, कोई awkवार्ड बाहरी प्रक्रिया; सिर्फ एक कांटा cp(कि आप किसी भी तरह से बच नहीं सकते हैं) और एक बैश ब्रेस विस्तार और ग्लोब (कि आप पूरी तरह से छुटकारा पा सकते हैं क्योंकि आप जानते हैं कि आपके पास कितनी फाइलें हैं)।


4
... और 2 मान्यताओं: फाइलें लगातार गिने जाती हैं और पहले वाला 4 से विभाज्य है।
manatwork

@manatwork कोई समस्या नहीं है अगर पहले एक 4 से विभाज्य नहीं है: उदाहरण के लिए, cp 00802_Bla_Aquarium_*{03..99..4}.jpg selectedयदि आप चाहते हैं 3 mod 4। (मैं अद्भुत तथ्य का उपयोग कर रहा हूं कि 100 4 से विभाज्य है)। अब, लगातार गिने फ़ाइलों के बारे में, अन्य सभी उत्तर समान हैं।
gnourf_gniourf

कौन से अन्य उत्तर निरंतर संख्या ग्रहण करते हैं? मुझे केवल उलरिक श्वार्ज की टिप्पणी और ऐसा कोई उत्तर नहीं मिला।
मैनटवर्क

5

बस बैश के साथ, आप कर सकते हैं:

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

पैटर्न ./*.jpgको बैश मैन द्वारा बताई गई फ़ाइल नामों की वर्णानुक्रम में क्रमबद्ध सूची से बदल दिया जाएगा, इसलिए इसे आपके उद्देश्य के अनुरूप होना चाहिए।


बैश में, forलूप के अंदर आपकी तीन लाइन को इस लाइन से बदला जा सकता है (((++n)%4)) || cp "$file" selected/:। ;-)। हालांकि समस्या यह है कि आप प्रत्येक फ़ाइल के cpलिए धन्यवाद कर रहे हैं जो वास्तव में कुशल नहीं है।
gnourf_gniourf

1

यदि आपने rubyस्थापित किया है तो आप निम्नलिखित एक-लाइनर का उपयोग कर सकते हैं। ध्यान दें कि यह मानता है कि चयनित निर्देशिका मौजूद है।

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

यह एक्सटेंशन के साथ सभी फाइलों की एक सूची लेता है। वर्तमान निर्देशिका में .jpg और इसे चार तत्वों की सूची में स्लाइस करता है और प्रत्येक सूची में पहले तत्व को वर्तमान निर्देशिका में चयनित निर्देशिका में कॉपी करता है।


1

यदि आप जानते हैं कि आपके फ़ाइल नामों में नई सीमाएँ नहीं होंगी, तो आप उपयोग कर सकते हैं:

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

@ गिल्स: संपादन के लिए धन्यवाद। मैंने 3 चर में फ़ाइल चर को हटा दिया हालांकि, जैसा कि मैं इंगित करना चाहता हूं कि उनकी आवश्यकता नहीं है।
jfg956

1

आप एक GUI फ़ाइल प्रबंधक का उपयोग कर सकते हैं और विंडो की सीमा का आकार बदल सकते हैं जब तक कि प्रत्येक 5 फाइलें एक पंक्ति पर कब्जा न कर लें, और फिर पहले कॉलम का चयन करने के लिए माउस का उपयोग करें ...


-1

Stackoverflow.com/q/4553751/789593 को देखते हुए जो हर दूसरे नंबर को @NN के रूप में कॉपी करने के लिए एक समाधान प्रस्तुत करता है, एक बहुत ही सरल समाधान होगा:

  • शुरुआती फ़ोल्डर से पहली फ़ाइल निकालें
  • शुरुआती फ़ोल्डर से इंटरमीडिएट फ़ोल्डर में हर दूसरे को कॉपी करें
  • मध्यवर्ती फ़ोल्डर से अंतिम फ़ोल्डर में हर दूसरे को कॉपी करें
  • पहली फ़ाइल मैन्युअल रूप से जोड़ें

यह बहुत कुशल नहीं हो सकता है क्योंकि इसके लिए एक अतिरिक्त प्रतिलिपि चरण की आवश्यकता होती है, जिसे करना बहुत आसान होना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.