'ओवरवोट' फाइलें, जगह अभी भी कब्जा कर ली गई हैं, क्या वे खो गए हैं?


11

तो गूंगा मुझे ढाल के साथ फ़ोल्डर में वीडियो फ़ाइलों का एक गुच्छा ले जाने के प्रयास में मेरे 19.04 सर्वर पर निम्न स्क्रिप्ट का उपयोग करता है:

dirs=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
shopt -s nocasematch

for file in *
do
    for dir in "${dirs[@]}"
    do

     if [ -d "$file" ]; then
      echo 'this is a dir, skipping'
      break
     else
      if [[ $file =~ ^[$dir] ]]; then
       echo "----> $file moves into -> $dir <----"
       mv "$file" "$dir"
       break
      fi
     fi
  done
done

कोई सुराग नहीं जहां यह गलत हुआ, लेकिन फाइलों को फ़ोल्डर्स में ले जाने के बजाय यह एक विलक्षण आउटपुट में चला गया .. इसलिए:

----> a1.ts moves into -> A <----
----> a2.ts moves into -> A <----
----> a3.ts moves into -> A <----
----> a4.ts moves into -> A <----
----> a5.ts moves into -> A <----
----> c1.ts moves into -> C <----
----> c2.ts moves into -> C <----
----> c3.ts moves into -> C <----
----> c4.ts moves into -> C <----
----> c5.ts moves into -> C <----

मैंने सौभाग्य से इस प्रक्रिया को बंद कर दिया (CTRL + C) जैसे ही मैंने देखा कि यह इरादा नहीं था और पूरे फ़ोल्डर में नहीं गया।

तो अब मैं उन फ़ाइलों को मिल गया है Aऔर Cहै, जो एक जीबी की तुलना में कम कर रहे हैं, और यह दिखता द्वारा एक वीडियो है।

फ़ोल्डर के कुल डिस्क उपयोग के लिए 50Gb बेहिसाब हैं, लेकिन कंप्यूटर का समग्र डिस्क स्थान एक ही रहा है। मुझे लगता है कि फ़ाइलें नष्ट नहीं कर रहे हैं?

किसी भी मदद की सराहना की, धन्यवाद :)

संपादित करें: फ़ाइलें वास्तव में चली गई हैं, केवल अंतिम फ़ाइल लिखी जानी बाकी है, डिस्क को अद्यतन करने के लिए जानकारी का उपयोग करने के लिए कुछ समय लग गया था .. कहानी का नैतिक, इससे पहले अपनी फाइलों को नकली फाइलों पर चलाएं!


3
और क्या स्क्रिप्ट को चलाने से पहले निर्देशिकाओं का नाम दिया गया था A, Bइत्यादि? यदि आप फ़ाइलों का नाम नहीं बदला है। वे सभी फाइलें जिनका नाम शुरू हुआ था aया जिनका नाम Aबदल दिया गया था A, इसलिए केवल अंतिम नामांकित फ़ाइल बच गई, अन्य को अधिलेखित कर दिया गया। एक चर को कॉल करने के dirलिए एक निर्देशिका नहीं बनाता है!
mook765

2
जिस तरह से यह व्याख्या के रूप में अच्छी तरह से। "अंतिम नामांकित फ़ाइल बच गई" हा। निर्देशिकाएं मौजूद नहीं थीं, मुझे हाथ से पहले प्रत्येक के लिए एक 'स्पर्श' जोड़ना चाहिए था। स्पष्ट करने के लिए धन्यवाद
मैं

4
+1 के लिए ".. कहानी का नैतिक, इससे पहले मॉक फ़ाइलों पर अपनी स्क्रिप्ट चलाएं!"
सुडोडस

4
इस तरह की समस्याओं से बचने के लिए एक टिप: mv "$file" "$dir/"एक अनुगामी के साथ उपयोग करें /; तो अगर $dirमौजूद नहीं है, mvनाम बदलने के बजाय त्रुटि जाएगा $fileकरने के लिए $dir। भी विचार mv -iऔर mv -n। और हमेशा एक mkdir -pउपाय करने से पहले, अच्छे उपाय के लिए।
मार्सेलम

3
@sudodus और भी बेहतर नैतिक, "हमेशा अपने डेटा का बैकअप लें!"।
जॉन बेंटले

जवाबों:


15

मुझे लगता है कि यह समस्या है: आपको निर्देशिका ए, बी, सी ... जेड बनाना mvचाहिए था। यदि आपने किया, तो कमांड को उन निर्देशिकाओं में फ़ाइलों को स्थानांतरित करना चाहिए।

लेकिन यदि नहीं, तो mvकमांड उन नामों, ए, बी, सी ... के साथ फाइलों को स्थानांतरित करता है और मुझे लगता है कि यह वही है जो आपने किया था।

गोले को सुरक्षित बनाने के लिए, आपको गति शुरू करने से पहले इसे निर्देशिका (यदि वे पहले से ही नहीं हैं) बनाना चाहिए।

dirs=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)

for dir in "${dirs[@]}"
do
 mkdir -p $dir
done

यदि आप चाहते हैं कि चीजें और भी सुरक्षित हों, तो आप विकल्प के mvसाथ भी उपयोग कर सकते हैं-i

   -i, --interactive
          prompt before overwrite

1
कई बार स्क्रिप्ट चलाने के मामले में संघर्ष से बचने के touchलिए एक अच्छा उपसमूह जोड़ना होगा mkdir?
मैं

2
touchएक फ़ाइल बनाता है यदि नाम मौजूद नहीं है। इसलिए यह वह नहीं करेगा जो आप इस मामले में चाहते हैं। mkdir -pकई बार स्क्रिप्ट का उपयोग कर संभाल सकता है।
सुडोडस

6
एक और सरल तरीका है कि आप mvसुरक्षित बना सकते हैं कि लक्ष्य नाम में एक अनुगामी स्लैश जोड़ने की आदत पड़ जाए जब लक्ष्य एक निर्देशिका हैmv "$file" "$dir/"
स्टीलड्राइवर

7

@ सूडोडस ने पहले ही बता दिया कि क्या गलत हुआ, लेकिन यहां अगली बार आपकी स्क्रिप्ट का एक सरल संस्करण है:

for letter in {a..z}; do 
    dir=${letter^}
    mkdir -p -- "$dir" 
    mv -- "$letter"* "${letter^^}"* "$dir"/
done

व्याख्या

  • for letter in {a..z}; do: {a..z}के बीच सभी लोअर केस अक्षरों के लिए विस्तारित aऔर z:

    $ echo {a..z}
    a b c d e f g h i j k l m n o p q r s t u v w x y z

    तो यह सभी निचले मामलों के पत्रों पर पुनरावृति करेगा, प्रत्येक के रूप में बचत करेगा $letter

  • dir=${letter^}: वाक्यविन्यास ऊपरी मामले में पहले चरित्र के साथ ${var^^}चर की सामग्री लौटाता है $var(क्योंकि इसमें केवल एक ही चरित्र है, यही हम सभी की आवश्यकता है)। तो, यदि $letterहै a, तो ${letter^^}है A, और इसलिए $dirवर्तमान का ऊपरी केस संस्करण होगा $letter

  • mkdir -p -- "$dir": डायरेक्टरी बनाएं। यदि यह पहले से मौजूद है, तो कुछ भी न करें ( -p)। -- विकल्पों के अंत का प्रतीक है , और के साथ शुरू नामों के खिलाफ की रक्षा के लिए उपयोगी है -
  • mv -- "$letter"* "${letter^}"* "$dir" : प्रत्येक फ़ाइल (या निर्देशिका) को प्रासंगिक लक्ष्य पर ले जाएं।

इसके साथ समस्या यह है कि यह आपके पास मौजूद किसी भी निर्देशिका को स्थानांतरित कर देगा। यह लक्ष्य निर्देशिकाओं को स्थानांतरित नहीं करेगा, क्योंकि या तो वे अभी तक मौजूद नहीं हैं, या आप उन्हें अपने आप में स्थानांतरित करने का प्रयास करेंगे, लेकिन कोई भी मौजूदा डायर जो लक्ष्य डायर नहीं हैं उन्हें स्थानांतरित किया जाएगा।

यदि यह समस्या है, तो आपको कुछ इस तरह करना होगा:

for file in *; do 
    if [[ ! -d "$file" ]]; then 
        letter="${file:0:1}"
        dir="${letter^}"
        mkdir -p -- "$dir"
        mv -- "$file" "$dir"/
    fi
done

बीच क्या अंतर है ${letter^}और ${letter^^}, और अगर वे समान हैं, यही कारण है कि उपयोग ${letter^^}के स्थान पर $dir?
फंड मोनिका का मुकदमा

1
@ नीचार्टले ${var^}पहले अक्षर को केवल कैपिटल करता है, जबकि ${var^^}सभी अक्षरों को कैपिटल करता है। यह यहाँ कोई फर्क नहीं पड़ता क्योंकि $letterकेवल एक पत्र है।
टेराडॉन

यह एक सटीक उत्तर है, सिवाय इसके कि आप कमांड $dirमें डायरेक्टरी स्लैश जोड़कर सावधानी की एक अतिरिक्त परत जोड़ना चाहते हैं mv। (अपने वर्तमान रूप में यह विफल हो जाएगा यदि एक एकल-अक्षर अपरकेस नाम के साथ एक फ़ाइल preexists)
स्टिग हेमर

@StigHemmer वूप्स, हाँ वास्तव में। बहुत अच्छी बात, धन्यवाद। उत्तर संपादित किया गया।
टेराडन

4

इसके बजाय हर फाइल को डिक्शनरी एरे के खिलाफ चेक करें जो बहुत से इटर्शन बनाता है जिससे आप फाइल को पैटर्न के खिलाफ मैच कर सकते हैं।

बहुत बुनियादी प्रकार:

#!/bin/bash

videos=./videos
sorted=./sorted

# sort types link,move.
sort_type=link

find "$videos" -maxdepth 1 -type f \
   \( -name '*.avi' -o -name '*.mkv' -o -name '*.mp4' \) -print0 |

while IFS= read -r -d ''; do

    b=$(basename "$REPLY")
    c=${b::1}

    case $c in
        [a-zA-Z]) label=${c^} ;; [0-9]) label="0-9" ;; *) label="_" ;;
    esac

    [[ ! -d "$sorted/$label" ]] && mkdir -p "$sorted/$label"

    if [[ -L $sorted/$label/$b ]] || [[ -e $sorted/$label/$b ]]; then
        echo "File/link: '$b' exists, skipping."
        continue
    fi

    case $sort_type in
        link)
            ln -rfst "$sorted/$label" -- "$REPLY"
            ;;
        move)
               mv -t "$sorted/$label" -- "$REPLY"
            ;;
    esac
done

शायद मैंने इसे गलत किया लेकिन निश्चित रूप से काम नहीं किया, दस फाइलें खो दीं। मैं REPLY भाग को समझते हुए दुखी हो रहा हूँ? क्या इरादा है कि सब छोड़ दिया गया है (फ़ोल्डरों के अंदर ABCD ....) खुद को इंगित करने वाली एलियास फाइलें हैं ... था उर्फ
मैं एक टीआई कैलकुलेटर हूं

जब कोई तर्क नहीं दिया जाता है तब रीड बिलिन कमांड द्वारा पढ़ी गई इनपुट की लाइन पर सेट किया जाता है।
bac0n

ठीक है और फिर अंत में आप ln -rfst "$ सॉर्टेड / $ लेबल" करते हैं - "$ REPLY" यदि हम सिर्फ उन्हें mv के साथ स्थानांतरित करते हैं तो उपनाम क्यों करते हैं?
मैं

डिफ़ॉल्ट रूप से यह आपके सॉर्ट की गई निर्देशिका में "वीडियो" निर्देशिका से लिंक बनाता है, यदि आप उन्हें एमवी करना चाहते हैं तो आपको "वीडियो स्थानांतरित करें" और "लिंक वीडियो" पर टिप्पणी करने की आवश्यकता है (मुझे लगता है कि
सहानुभूति

... बस एक ही समय पर दोनों नहीं।
22

2

अपने .bashrc में सुरक्षित रखें:

alias mv="mv -n --backup=numbered"

1
@Zanna, इसके लिए धन्यवाद! जोड़े गए उद्धरण।

कुछ सवाल बस यकीन है कि (एक नौसिखिया होने के नाते), .zshrc फ़ाइल में जोड़ना भी मान्य है (यदि ZSH का उपयोग कर रहा है)? में आदमी एमवी यह कहते हैं -n Do not overwrite an existing file. (The -n option overrides any previous -f or -i options.)तो यह फर्क पड़ता है कि -n टैग टैग पालन करने से पहले हो जाएगा? --Backup गिने = प्रत्येक सही का एक डबल पैदा करेगा, न कि एक सा overkill (और अंतरिक्ष ऊर्जा / लेने वाली) जब uber-बड़ी वीडियो फ़ाइलों के साथ काम कर (बात कर टेराबाइट्स) है। धन्यवाद !
मैं

2

रिकॉर्ड के लिए, mvमौजूदा फ़ाइलों को अधिलेखित करने से रोकने के कुछ तरीके :

  • यदि आप किसी निर्देशिका में जाना चाहते हैं, तो लक्ष्य के लिए एक स्लैश जोड़ें, अर्थात के mv "$file" "$dir"/बजाय उपयोग करें mv "$file" "$dir"। यदि $dirमौजूद नहीं है या निर्देशिका नहीं है, mvतो शिकायत करेंगे:

    $ touch a
    $ mv a z/
    mv: cannot move 'a' to 'z/': Not a directory
    $ touch z
    $ mv a z/
    mv: failed to access 'z/': Not a directory

    यह सिस्टम कॉल करने के लिए लगता है rename("a", "z/"), इसलिए यह समय-समय पर चेक-ऑफ-टाइम-उपयोग कमजोरियों से सुरक्षित होना चाहिए, यदि कोई व्यक्ति एक ही समय में फ़ाइलों के एक ही सेट को संभाल रहा है।

  • वैकल्पिक रूप से, उपयोग करें mv -t "$dir" "$file"। फिर, अगर $dirयह एक निर्देशिका नहीं है तो शिकायत करेंगे ।

  • -nमौजूदा फ़ाइलों को ओवरराइट करने से रोकने के लिए विकल्प का उपयोग करें :

    -n, --no-clobber
        do not overwrite an existing file

    यह इसे पहली फ़ाइल का नाम बदलने से नहीं रोकेगा, लेकिन फिर इसे दूसरों के साथ कचरा नहीं करेगा।

    यह एक सादा कॉल लगता है rename(), इसलिए यह एक साथ हैंडलिंग के साथ सुरक्षित नहीं हो सकता है। (ऐसा है renameat2()जो ओवर राइटिंग को रोकने के लिए एक ध्वज का समर्थन करेगा।)


1

हालांकि स्पष्ट रूप से आपके लिए मामला नहीं है, यह संभव है कि आप ऐसा कर सकते हैं और फाइलों को नहीं खो सकते हैं। इसके लिए दो चीजों में से एक को सही होना आवश्यक है:

  • एक या एक से अधिक 'हार्ड लिंक' फाइलों में कहीं और मौजूद हैं
  • एक या अधिक प्रक्रियाओं में एक फ़ाइल खुली होती है

यूनिक्स फाइलसिस्टम एक से अधिक डायरेक्टरी प्रविष्टि को सटीक एक ही फाइल कंटेंट को संदर्भित करने की अनुमति देता है । इसे ' हार्ड लिंक ' कहा जाता है । आप सामान्य (नरम / प्रतीकात्मक) विकल्प के बिनाln , कमांड के साथ हार्ड लिंक बना सकते हैं । जब तक कम से कम एक हार्ड लिंक फ़ाइल सामग्री में मौजूद है, तब तक इसे फाइल सिस्टम द्वारा पुन: उपयोग नहीं किया जाएगा।-s

(साइड नोट, अनुमतियाँ आमतौर पर फ़ाइल सामग्री पर लागू होती हैं, निर्देशिका प्रविष्टि के लिए नहीं। यही कारण है कि एक साधारण उपयोगकर्ता कभी-कभी किसी फ़ाइल को स्वामित्व में हटा सकता है root, लेकिन उसे लिख नहीं सकता है। हटाने का कार्य फ़ाइल को नहीं, बल्कि फ़ोल्डर को संशोधित करता है। )

जब तक कम से कम एक प्रक्रिया में फ़ाइल खुली न हो, फ़ाइल सिस्टम फ़ाइल सामग्री का पुन: उपयोग नहीं करेगा। यहां तक ​​कि अगर कोई निर्देशिका प्रविष्टि मौजूद नहीं है, तो फ़ाइल सिस्टम रिक्त स्थान पर विचार नहीं करेगा जब तक कि कोई प्रक्रिया न हो। फ़ाइल बरामद किया जा सकता आभासी फाइल सिस्टम से /proc/<pid>/fdद्वारा rootजब तक फ़ाइल के रूप में खुला रहता है। (साभार @fluffysheap।)


1
यदि फ़ाइल खोलने के साथ कोई प्रक्रिया होती है, तो आप इसे / proc / <pid> / fd में देख कर पुनर्प्राप्त कर सकते हैं। देखें superuser.com/questions/283102/...
fluffysheap
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.