गंतव्य निर्दिष्ट किए बिना `mv ./*` क्या करता है?


27

मैं गलती से रिटर्न कुंजी मारने से पहले गंतव्य निर्दिष्ट करना भूल गया। mv ./*गंतव्य को निर्दिष्ट किए बिना, वर्तमान निर्देशिका के अंतर्गत फ़ाइलों और निर्देशिकाओं को कहाँ स्थानांतरित करें?



4
"मुझे आश्चर्य है कि mv1 तर्क स्वीकार करता है" यह नहीं है। यह उन सभी तर्कों को स्वीकार करता है जो शेल विस्तार करने के बाद उसे पारित करता है *
glglgl

जवाबों:


41

यदि अंतिम तर्क एक निर्देशिका था, तो आपने अपनी वर्तमान कार्यशील निर्देशिका में उन सभी फ़ाइलों और निर्देशिकाओं को छोड़ दिया था (सिवाय जिनके नाम डॉट्स से शुरू होते हैं) उस निर्देशिका में। यदि दो फ़ाइलें थीं, तो पहली फ़ाइल ने दूसरी फ़ाइल अधिलेखित कर दी हो सकती है।

यहाँ कुछ प्रदर्शन हैं:

दो से अधिक फाइलें और अंतिम तर्क एक फाइल है

$ mkdir d1 d2 d3
$ touch a b c e
$ mv *
mv: target 'e' is not a directory

दो से अधिक फाइलें और अंतिम तर्क एक निर्देशिका है

$ mkdir d1 d2 d3
$ touch a b c
$ mv -v *
'a' -> 'd3/a'
'b' -> 'd3/b'
'c' -> 'd3/c'
'd1' -> 'd3/d1'
'd2' -> 'd3/d2'

दो फाइलें

$ touch a b
$ mv -v *
'a' -> 'b'

आगे की व्याख्या

खोल ग्लोब ( *) के लिए तर्कों में विस्तार करता है mv। ग्लोब का विस्तार आमतौर पर वर्णमाला क्रम में किया जाता है। mvहमेशा फ़ाइलों और निर्देशिकाओं की सूची देखता है। यह कभी भी ग्लोब को नहीं देखता है।

कमांड mvदो प्रकार की चलती का समर्थन करता है। एक है mv file ... directory। दूसरा है mv old-file-name new-file-name(या mv old-file-name directory/new-file-name)।


30

पहले मैं एक परीक्षण आधार बनाऊंगा - 5 फाइलें और एक फ़ोल्डर:

touch file1 file2 file3 file4 file5
mkdir folder

आगे मैं एक टेस्ट कमांड चलाऊंगा। -vविकल्प निर्दिष्ट करता है मैं हर आदेश खोल कार्यान्वित करने के लिए मुद्रित किया जा करना चाहते हैं कि stderr-xविकल्प निर्दिष्ट करता है कि मैं चाहता हूँ एक ही करने के लिए मुद्रित stderr- लेकिन मैं यह किया चाहते हैं के बाद आदेश का मूल्यांकन किया जाता है, लेकिन इससे पहले कि खोल यह चलाता है।

sh -cxv 'echo mv *'

आउटपुट

echo mv *
+ echo mv file1 file2 file3 file4 file5 folder
mv file1 file2 file3 file4 file5 folder

तो आप देखते हैं कि आदेश मैं फ़ीड खोल है echo mv *और कमांड खोल कार्यान्वित के बाद * का विस्तार किया गया है echo mvउन फ़ाइलों और फ़ोल्डर के सभी के द्वारा पीछा किया।

डिफ़ॉल्ट रूप से शेल ग्लब्स का विस्तार करेगा जैसे:

sh -cxv 'echo file[1-5]'

आउटपुट

echo file[1-5]
+ echo file1 file2 file3 file4 file5
file1 file2 file3 file4 file5

यह set [+-]fग्लोब फंक्शन का परिणाम है :

sh -cxvf 'echo file[1-5]'

आउटपुट

echo file[1-5]
+ echo 'file[1-5]'
file[1-5]

इसलिए जब आप शेल में एक कमांड को डिफॉल्ट विकल्पों के साथ कॉन्फ़िगर करते हैं, जैसे mv *शेल *शब्द में फैलता है तो लोकल के अनुसार सॉर्ट की गई डायरेक्टरी में सभी फाइलों की एक तर्क सूची होती है। यह इस तर्क सूची के साथ (अनिवार्य रूप से) केexec(ve) लिए syscall संलग्न है। तो सभी तर्क मिलते हैं क्योंकि शेल उन्हें ग्लोब करता है और उन्हें सॉर्ट करता है। इन प्रभावों को देखने के अलावा , आप डिबग को फिर से उपयोग कर सकते हैं जैसे:mv mvstrace

sh -s -- mv * <<\SCRIPT
sed -n l /proc/$$/cmdline
echo "$@"
SCRIPT

आउटपुट

sh\000-s\000--\000mv\000file1\000file2\000file3\000file4\000file5\000folder\
\000$
mv file1 file2 file3 file4 file5 folder

और सुस्पष्ट रूप से:

( PS4= IFS=/; set -x mv *; : "/$*/" ) 2>&1

आउटपुट

: /mv/file1/file2/file3/file4/file5/folder/

मूल रूप से, शेल अपनी तर्क सूची के रूप mvमें निर्देशिका की सामग्री के साथ निष्पादित होता है (यदि यह खाली नहीं है और शुरुआत के नाम के साथ फाइल / फ़ोल्डर शामिल नहीं है .)mvPOSIX एक निर्देशिका के रूप में अपने अंतिम तर्क की व्याख्या करने के लिए निर्दिष्ट है यदि इसे दो से अधिक तर्कों के साथ लागू किया जाता है - उसी तरह से lnहै (क्योंकि वास्तव में, वे अंतर्निहित फ़ंक्शन में अविश्वसनीय रूप से समान उपकरण हैं)

echoहालांकि पर्याप्त :

sh -cxv 'mv *' ; ls

आउटपुट

mv *
+ mv file1 file2 file3 file4 file5 folder
folder/

सभी फाइलें अंतिम तर्क में स्थानांतरित हो गईं - क्योंकि यह एक फ़ोल्डर है। अब अगर यह एक फ़ोल्डर नहीं है तो क्या होगा?

sh -cxv 'cd *; mv *'; ls . *

आउटपुट

cd *; mv *
+ cd folder
+ mv file1 file2 file3 file4 file5
mv: target ‘file5’ is not a directory

.:
folder/

folder:
file1  file2  file3  file4  file5

यह है कि कैसे POSIX निर्दिष्ट करता mv है कि मामले में व्यवहार करना चाहिए:

mv [-if] source_file target_file

mv [-if] source_file... target_dir

पहले सिनोप्सिस रूप में, mvउपयोगिता source_file ऑपरेंड द्वारा नामित फ़ाइल को लक्ष्य-फ़ाइल द्वारा निर्दिष्ट गंतव्य तक ले जाएगी । यह पहला सिनॉप्सिस फॉर्म माना जाता है जब अंतिम ऑपरेंड एक मौजूदा निर्देशिका का नाम नहीं देता है और एक मौजूदा निर्देशिका का संदर्भ देने वाला एक प्रतीकात्मक लिंक नहीं है। इस स्थिति में, यदि source_file एक गैर-निर्देशिका फ़ाइल का नाम देता है और target_file एक अनुगामी /slashवर्ण के साथ समाप्त होता है , mvतो इसे एक त्रुटि के रूप में माना जाएगा और कोई source_file ऑपरेंड संसाधित नहीं किया जाएगा।

दूसरे सिनॉप्सिस रूप में, mvsource_file operand द्वारा नामित प्रत्येक फ़ाइल को मौजूदा निर्देशिका में target_dir ऑपरेंड द्वारा नामित गंतव्य फ़ाइल में ले जाया जाएगा , या संदर्भित किया जाएगा यदि target_dir एक मौजूदा निर्देशिका का संदर्भ देने वाला एक प्रतीकात्मक लिंक है। प्रत्येक source_file के लिए गंतव्य पथ लक्ष्य निर्देशिका का संघटन होगा, /slashयदि लक्ष्य a में समाप्त नहीं हुआ है /slash, तो एक एकल वर्ण और source_file का अंतिम pathname घटक । यह दूसरा रूप तब माना जाता है जब अंतिम ऑपरेंड एक मौजूदा निर्देशिका का नाम देता है।

इसलिए यदि इसका *विस्तार होता है:

  • दो फाइलें

    • आपके पास केवल एक फ़ाइल होनी चाहिए, जो renamedदूसरी के बाद पहली से दूसरी है unlinked
  • एक या एक से अधिक फ़ाइलों को एक निर्देशिका या एक के बाद एक लिंक के बाद पिछले

    • आपके पास केवल एक निर्देशिका या एक लिंक होना चाहिए, जो कि उसके माता-पिता की सभी पिछली सामग्री को अभी स्थानांतरित किया गया हो।
  • और कुछ

    • आपके पास एक त्रुटि संदेश और राहत की संतोषजनक संतुष्टि होनी चाहिए।

1
हां, पुरानी shबात का उपयोग करते हुए , मैं उस के साथ डिबगिंग के बारे में भूल गया, लेकिन मेरे मूल प्रश्न के बारे में, इसका मतलब है कि समस्या शेल नहीं है mv? यह बुरा है, यह मूल रूप से आसान है जितना मैंने सोचा था लेकिन यह एक वास्तविक जाल है।
user2485710

5
@ user2485710, प्रमुख बिंदु यह है कि यूनिक्स में कमांड लाइन के तर्क को पारित करने से पहले वाइल्डकार्ड के विस्तार के लिए शेल जिम्मेदार है। विंडोज में, प्रत्येक कमांड को वाइल्डकार्ड का विस्तार करना होगा। यह यूनिक्स गोले को उन्नत वाइल्डकार्ड सुविधाओं की पेशकश करने की अनुमति देता है जो किसी भी कमांड के साथ काम करते हैं।
cjm

2
@mikeserv ने इस तथ्य को देखते हुए कहा कि वे फाइलें महत्वपूर्ण नहीं थीं कि मैं खुद को सफाई करने के लिए ले गया और अगले चरण पर छोड़ दिया, लेकिन मैं चीजों की पुष्टि कर सकता हूं क्योंकि वे अब मेरे पहले पोस्ट / प्रश्न के मेरे संपादन में दिखाई देते हैं।
user2485710

6
@ mikeserv tl? डॉ, *एक भी तर्क नहीं है? सही? :)
बर्नहार्ड

1
@ बर्नहार्ड - वास्तव में, यह एक मामला है जिसे मैंने कवर नहीं किया - क्योंकि यह हो सकता है।
mikeserv

18

पहले शेल ./*वर्तमान निर्देशिका में सभी फ़ाइलों तक फैलता है (डॉट के साथ शुरू होने वाली फ़ाइलों को छोड़कर)।

  • अगर कोई या केवल एक फ़ाइल नहीं है: mvविफल रहता है
  • अगर दो फ़ाइल हैं: पहले वाले को दूसरे में ले जाया गया है (जो इसलिए खो गया)
  • यदि दो से अधिक फाइलें हैं:
    • यदि अंतिम एक निर्देशिका है: सभी फ़ाइलों को इस निर्देशिका में ले जाया जाता है
    • अन्यथा mvविफल रहता है।

1
धन्यवाद। कैसे बताएं कि कौन सा उपनिर्देशिका "अंतिम एक" है?
टिम

7
बस कॉल करें echo ./*यह देखें कि आपका शेल किस ऑर्डर का उपयोग करता है (आमतौर पर वर्णमाला)।
जोफेल

यदि यह एक फ़ाइल के साथ विफल हो जाता है तो ऐसा क्यों नहीं कहा जाता है?
नूमेनन

@ नोमैनन मैं आपकी टिप्पणी को नहीं समझता। mvयदि यह केवल एक तर्क के साथ कहा जाता है, तो एक त्रुटि संदेश देता है।
जोफेल

तुम सही हो। मेरे इतिहास का वही आदेश अब missing destination file operand after *filename*भी देता है जबकि कल यह नहीं था।
नौमेनन

4

जब आप टाइप करते हैं mv ./*, तो ./*निष्पादित करने से पहले आपके शेल का विस्तार होगा mv

ध्यान देने योग्य कुछ बातें:

  • अगर ./*2 से कम तर्कों में विस्तारित किया जाता है mv, तो तार्किक रूप से, एक त्रुटि पैदा करेगा।
  • ./* आमतौर पर वर्तमान निर्देशिका में मौजूद हर फ़ाइल (निर्देशिका सहित) में विस्तार होगा और डॉट के साथ शुरू नहीं होगा।
  • आप ./*अपने शेल के प्रलेखन को पढ़कर ( man 7 globजो विषय का एक प्रवेश बिंदु है) विस्तार कर सकते हैं। अलग-अलग गोले के अलग-अलग विकल्प होंगे।

1

क्या करता mv *है?

यहाँ एक छोटा जवाब है:

शेल वाइल्डकार्ड *को निर्देशिका सामग्री की सूची में विस्तारित करता है । फिर शेल उस पूरी सूची को कमांड में भेजता है। आज्ञा कभी नहीं देखता *

कमांड mv file1 file2 ... filen directoryfile1 ... निर्देशिका में फ़ाइल किया जाएगा।

उदाहरण

यहाँ मैं तीन फ़ाइलों वाली एक परीक्षण निर्देशिका बनाता हूँ

$ mkdir t
$ cd t
$ echo a>a; echo b>b; echo c>c
$ ls
a  b  c

आप एक फ़ाइल में एकाधिक फ़ाइलों को स्थानांतरित नहीं कर सकते

$ mv *
mv: target `c' is not a directory

चलो एक उपनिर्देशिका जोड़ें

$ mkdir d

आप कई फ़ाइलों को एक उपखंड में स्थानांतरित कर सकते हैं

$ mv *
$ ls
d
$ ls d
a  b  c

कमांड के mv file1 file2 ... filen directoryपास कुछ भी करने की संभावना बहुत कम है *
15

@ माइक: मेरा उत्तर बताता है कि शेल विस्तार का अंतिम चरण बाद में पूर्व में प्रभावी रूप से बदल जाता है। यह न जानना ओपी के भ्रम की जड़ प्रतीत होता है।
RedGrittyBrick

हाँ, लेकिन मेरी बात खोल विस्तार नहीं होता है *में file dirजब तक कि वहाँ कुछ लोकेल जिसमें है dइस प्रकार है f
मोकेसर

@mikeserv: इस तरह का एक लोकेल है, मेरा उदाहरण पुट्टी से सेंटोस 5.6 जीएनयू / लिनक्स सिस्टम से कनेक्ट और कट है।
RedGrittyBrick

वह कौन सा स्थान है? आपका उदाहरण a b c dजो नहीं है file ... dir। मैं केवल सब पर टिप्पणी की है क्योंकि आप तरह कहीं भी उल्लेख नहीं है और कहते हैं कि केवल यह है कि *हो जाता है file ... dirजो नहीं होता है।
mikeserv
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.