mv: यदि गंतव्य मौजूद नहीं है तो फ़ाइल को स्थानांतरित करें


44

मैं उपयोग कर सकते हैं mv file1 file2एक तरह से है कि यह केवल चालें file1करने के लिए file2करता है, तो file2मौजूद नहीं है?

मैंने कोशिश की

yes n | mv -i file1 file2

(यह mvपूछने देता है कि क्या फ़ाइल 2 को ओवरराइड किया जाना चाहिए और स्वचालित रूप से उत्तर नहीं देना चाहिए) लेकिन -iइसका दुरुपयोग करने के अलावा मुझे अच्छा त्रुटि कोड भी नहीं देता है (हमेशा 0 के बजाय 141 और अगर स्थानांतरित नहीं हुआ तो कुछ और)


3
आपके पास pipefailविकल्प होना चाहिए क्योंकि 141 से बाहर निकलने की स्थिति होगी yes, न mvकि जिसके कारण यहां एक SIGPIPE प्राप्त करने का कोई कारण नहीं होगा।
स्टीफन चेज़लस

यदि फ़ाइल 2 एक निर्देशिका है (तो यह फ़ाइल 1 निर्देशिका में फ़ाइल 1 को स्थानांतरित कर देगा)। GNU mv उसके लिए एक -Tहै।
स्टीफन चेज़लस

@ स्टीफनचेलजैस यदि इच्छा के mvबजाय बाहर निकलने की स्थिति का उपयोग करना है yes, तो सबसे सरल उपाय हो सकता हैmv -i file1 file2 < <(yes n)
कैस्पर

जवाबों:


63

mv -vn file1 file2। यह कमांड वही करेगा जो आप चाहते हैं। आप चाहें तो स्किप कर सकते -vहैं।

-v यह क्रिया करता है - एमवी आपको बताएगा कि यह स्थानांतरित हो गई है तो फ़ाइल चली गई है (उपयोगी है, क्योंकि संभावना है कि फ़ाइल नहीं होगी)

-n केवल तभी चलता है जब फ़ाइल 2 मौजूद नहीं है।

कृपया ध्यान दें यह है कि इस POSIX नहीं है के रूप में ThomasDickey ने उल्लेख किया


2
हालाँकि, यह POSIX नहीं है ।
थॉमस डिके

1
@ThomasDickey क्या POSIX इसका समर्थन परमाणु तरीके से करता है?
Fabian Schmitthenner

3
@ फ़ेबियन: शायद नहीं, लेकिन सुझाए गए उत्तरों के भीतर भी टूल के भीतर एक दौड़ की संभावना है, यह निर्भर करता है कि वे कैसे लिखे गए हैं।
थॉमस डिके

3
ऐसा लगता है straceकि यह रेस फ्री नहीं है, यह दिखाता है कि यह (मेरे सिस्टम पर) का उपयोग करता है: स्टेट ("file2", 0x7ffe3e705d10) = -1 ENOENT (ऐसी कोई फ़ाइल या निर्देशिका) lstat ("file1"), {st_mode = S_IFREG | 0644 | st_size = 0, ...}) = 0 lstat ("file2", 0x7ffe3e705a10) = -1 ENOENT (ऐसी कोई फ़ाइल या निर्देशिका नहीं) का नाम बदलें ("file1", "file2" = 0 lseek (0, 0, SEEK_CUR) = -1 ईएसपीआईपीई (अवैध साधक)। इसलिए नाम बदला हुआ मालूम पड़ता है। यदि आप वास्तव में इसे मुफ्त में करना चाहते हैं, तो स्टीफनचेज़लस समाधान सही प्रतीत होता है।
फेबियन शमिथेनर

2
मुझे आश्चर्य है कि इसका उपयोग क्यों नहीं किया जाता हैrenameat2
फेबियन शमिथेनर

16

mv -n

से man mvएक जीएनयू सिस्टम पर:

-n, -no-clobber
किसी मौजूदा फ़ाइल को अधिलेखित नहीं करता है

एक FreeBSD सिस्टम पर:

-nकिसी मौजूदा फ़ाइल को अधिलेखित न करें। (-N विकल्प किसी भी पिछले -f या -i विकल्प को ओवरराइड करता है।)


10
if [ ! -e file2 ] && [ ! -L file2 ]
then
    mv file1 file2
# else echo >&2 there is already a file2 file.
fi

या:

if ! ls -d file2 > /dev/null 2>&1
then
    mv file1 file2
fi

केवल मौजूद होगा mvयदि file2मौजूद नहीं है। ध्यान दें कि यह गारंटी नहीं देता है कि file2अतिप्रश्न नहीं किया जाएगा क्योंकि file2परीक्षण और के बीच बनाया जा सकता था mv, लेकिन ध्यान दें कि GNU के कम से कम वर्तमान संस्करण के mvसाथ -iया -nतो वह गारंटी नहीं देते हैं (हालांकि दौड़ की स्थिति संकीर्ण है। वहाँ जाँच के बाद से किया जाता है mv)।

दूसरे छोर पर, यह पोर्टेबल है, आपको मामलों के बीच भेदभाव करने की अनुमति देता है, और file2फ़ाइल के प्रकार (नियमित, पाइप, यहां तक ​​कि निर्देशिका ) की परवाह किए बिना काम करता है ।


3
क्या यह एक दौड़ की स्थिति का परिचय देता है जहाँ अस्तित्व की जाँच और चाल के बीच एक फ़ाइल लिखी जा सकती है?
फैबियन शमिथेनर

3
हमेशा एक संभावना जो भी आप करते हैं।
मजनू

3
लिनक्स एपीआई में renameat2आप एक RENAME_NOREPLACEझंडा दे सकते हैं । मेरा मानना ​​है कि यह परमाणु अस्तित्व की जाँच करता है और फिर फ़ाइल को स्थानांतरित करता है।
फाबियन शमिथेनर

निर्देशिका के लिए -d, या लिंक के लिए -l, या यहां तक ​​कि किसी भी फ़ाइल प्रकार के लिए
Majenko

नाम बदलकर दौड़ मुक्त हो सकता है, लेकिन बाकी के mv कमांड नहीं है। अगर यह सोचता है कि इसे अनलिंक करने की आवश्यकता नहीं है, तो अचानक नाम बदलने में विफल रहता है (यह) त्रुटि होनी चाहिए।
मजेंको

8

जीएनयू के साथ एक दौड़ से मुक्त दृष्टिकोण lnप्रदान की file1प्रकार की नहीं है निर्देशिका :

ln -PT file1 file2 && rm file1

(कुछ नेटवर्क फ़ाइल सिस्टम में बग को छोड़कर), यह गारंटी देता है कि कोई भी file2फ़ाइल ओवरराइड नहीं होगी (या यदि file2वह टाइप डायरेक्टरी की है, file1तो उसमें ले जाया नहीं जाएगा), क्योंकि link()सिस्टम कॉल, सिस्टम कॉल के विपरीत, rename()विफल हो जाएगा यदि लक्ष्य मौजूद है।

हालांकि, एक मध्यवर्ती राज्य होगा जहां फ़ाइल दोनों के रूप में मौजूद है file1और file2

-Tविकल्प (हमेशा एक ऐसा करने के लिए link("file1", "file2")भले ही file2प्रकार निर्देशिका की है) जीएनयू-विशिष्ट है।

आप linkकमांड का उपयोग भी कर सकते हैं :

link file1 file2 && rm file1

हालाँकि, यदि file1कार्यान्वयन के आधार पर, एक सिमलिंक है, file2तो उस सिम्लिंक के लिए एक हार्डलिंक होगा या उस सिम्लिंक के लक्ष्य पर (सोलारिस, उपयोग /usr/sbin/link, नहीं /usr/xpg4/bin/link)।


2
क्या आपको पता है कि renameat2झंडे के साथ linux api RENAME_NOREPLACEपरमाणु है?
फैबियन शमिथेनर

1
@ फैबियन, AFAICT, लेकिन यह बहुत नया है और सभी फाइल सिस्टम के लिए समर्थित नहीं है। आगे जाकर, हम उपयोग करने के लिए लिनक्स पर भविष्य के एमवी कार्यान्वयन की उम्मीद कर सकते हैं। इसे ही इसके लिए डिजाइन किया गया था।
स्टीफन चेजलस

0

आप यह भी उपयोग कर सकते हैं test -e nameकि अगर नाम मौजूद है (फाइल, निर्देशिका या सिम्लिंक की परवाह किए बिना) तो यह सच हो जाएगा।

उदाहरण के लिए:

touch file
mkdir dir
ln -s file symlink
test -e file && echo file exists
test -e dir && echo dir exists
test -e symlink && echo symlink exists
test -e file || echo you wont see this echo
test -e doesnotexist || echo doesnotexist does not exist...

1
लेकिन ln -s doesnotexist exists; test -e exists || echo "does it really not exist?"। उदाहरण के लिए एक ही ln -s /var/spool/cron/crontabs/. exists(और आप रूट या crontab समूह के सदस्य नहीं हैं)।
स्टीफन चेज़लस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.