अगर यह मौजूद नहीं है, तो क्या एमवी बनाने के लिए निर्देशिका बनाने का एक तरीका है?


275

इसलिए, अगर मैं अपने होम डायरेक्टरी में हूं और मैं foo.c को ~ / bar / baz / foo.c में ले जाना चाहता हूं, लेकिन उन निर्देशिकाओं का अस्तित्व नहीं है, तो क्या उन निर्देशिकाओं को स्वचालित रूप से बनाने का कोई तरीका है, ताकि आपको केवल लिखना होगा

mv foo.c ~/bar/baz/ 

और सब कुछ बाहर काम करेगा? ऐसा लगता है कि आप एक साधारण bash स्क्रिप्ट को alias mv कर सकते हैं जो यह जाँच करेगा कि क्या उन निर्देशिकाओं का अस्तित्व है और यदि नहीं तो mkdir और फिर mv को कॉल करेंगे, लेकिन मैंने सोचा कि मैं यह देखने के लिए जांच करूंगा कि क्या किसी के पास बेहतर विचार था।


जवाबों:


294

इस वन-लाइनर के बारे में कैसे (बाश में):

mkdir --parents ./some/path/; mv yourfile.txt $_

इसे तोड़कर:

mkdir --parents ./some/path

निर्देशिका बनाता है (सभी मध्यवर्ती निर्देशिका सहित), जिसके बाद:

mv yourfile.txt $_

उस निर्देशिका में फ़ाइल को स्थानांतरित करता है ($ _ पिछले शेल कमांड को दिए गए अंतिम तर्क तक फैलता है, अर्थात: नई बनाई गई निर्देशिका)।

मुझे यकीन नहीं है कि यह अन्य गोले में कितनी दूर काम करेगा, लेकिन यह आपको कुछ विचार दे सकता है कि क्या देखना है।

इस तकनीक का उपयोग कर एक उदाहरण दिया गया है:

$ > ls
$ > touch yourfile.txt
$ > ls
yourfile.txt
$ > mkdir --parents ./some/path/; mv yourfile.txt $_
$ > ls -F
some/
$ > ls some/path/
yourfile.txt


1
./हर जगह बेमानी से जुनून क्यों ? पीएटीएच में .निर्देशिका के बिना आर्ग्स कमांड नहीं हैं ...
जेन्स

3
Newbies के लिए, --parents को -p
sakurashinken

8
अजीब तरह से, --parentsmacOS 10.13.2 पर उपलब्ध नहीं है। आपको उपयोग करने की आवश्यकता है -p
यहोशू पिंजर

1
यदि फ़ाइल को स्थानांतरित करना काम नहीं करता है जैसे ./some/path/foo। इस मामले में कमांड होनी चाहिए:mkdir -p ./some/path/foo; mv yourfile.txt $_:h
hhbilly

63
mkdir -p `dirname /destination/moved_file_name.txt`  
mv /full/path/the/file.txt  /destination/moved_file_name.txt

2
मैं इस कोड को महसूस करने के लिए केवल एक ही हूं जिसका कोई मतलब नहीं है? आप मौजूदा फ़ाइल (जिसका अर्थ है कि यह पथ पहले से मौजूद है) के लिए पुनरावर्ती पथ बनाते हैं और फिर फ़ाइल को किसी स्थान पर ले जाते हैं (जो आपके उदाहरण में मौजूद नहीं है)।
vdegenne 19

1
@ user544262772 GNU Coreutils ' dirnameको इसके तर्क की आवश्यकता नहीं है, यह शुद्ध स्ट्रिंग हेरफेर है। अन्य वितरणों के लिए नहीं बोल सकते। इस कोड afaict के साथ कुछ भी गलत नहीं है।
ट्रॉयहर्ट्स

यह उत्तर है जो सबसे आसानी से स्वचालित है, मुझे लगता है। for f in *.txt; do mkdir -p `dirname /destination/${f//regex/repl}`; mv "$f" "/destination/${f//regex/repl}; done
काइल

23

Mv या mv.sh नाम की स्क्रिप्ट के रूप में सहेजें

#!/bin/bash
# mv.sh
dir="$2"
tmp="$2"; tmp="${tmp: -1}"
[ "$tmp" != "/" ] && dir="$(dirname "$2")"
[ -a "$dir" ] ||
mkdir -p "$dir" &&
mv "$@"

या अपने ~ / .bashrc फ़ाइल के अंत में एक फ़ंक्शन के रूप में रखें जो हर नए टर्मिनल पर डिफ़ॉल्ट एमवी को बदलता है। किसी फ़ंक्शन का उपयोग करने से बैश को हर बार स्क्रिप्ट फ़ाइल पढ़ने के बजाय मेमोरी को बनाए रखने की अनुमति मिलती है।

function mv ()
{
    dir="$2"
    tmp="$2"; tmp="${tmp: -1}"
    [ "$tmp" != "/" ] && dir="$(dirname "$2")"
    [ -a "$dir" ] ||
    mkdir -p "$dir" &&
    mv "$@"
}

ये क्रिस लुट्ज़ की अधीनता पर आधारित थे।


3
यह प्रश्न का सबसे सटीक IMHO उत्तर देता है। उपयोगकर्ता एक बढ़ी हुई mvकमांड पसंद करेगा । स्क्रिप्टिंग के लिए विशेष रूप से उपयोगी है, यानी आप जरूरी नहीं कि चेक चलाना चाहते हैं और mkdir -pकभी भी उपयोग करने की आवश्यकता हो mv। लेकिन जब से मैं डिफ़ॉल्ट त्रुटि व्यवहार चाहता mvहूं, मैंने फ़ंक्शन का नाम बदल दिया है mvp- ताकि मुझे पता चले कि मैं निर्देशिका कब बना सकता हूं।
ब्रायन डंकन

सबसे अच्छा समाधान विचार की तरह लगता है, लेकिन कार्यान्वयन बहुत बड़ा है।
उलिसे लीरा

2
@UlisesLayera I ने इसे और अधिक मजबूत बनाने के लिए एल्गोरिदम को संशोधित किया। यह अब दुर्घटना नहीं होनी चाहिए
सेपरो

क्या कोई कृपया [ ! -a "$dir" ]मुझे समझा सकता है कि मैंने सही आधे और सच्चे होने के साथ प्रयोग किए हैं, दोनों का मूल्यांकन सही है .. ??? अन्य की खातिर, tmp = "$ {tmp: -1}" फ़ाइल का अंतिम वर्ण
हड़पता हुआ

@bazz यह करना चाहिए "अगर $ dir मौजूद नहीं है, तो जारी रखें"। दुर्भाग्य से, आप सही हैं, "-a" का उपयोग करते समय एक बग है, और मुझे नहीं पता कि क्यों। मैंने कोड को थोड़ा संपादित किया है, और अब काम करना चाहिए।
सेपरो

13

आप उपयोग कर सकते हैं mkdir:

mkdir -p ~/bar/baz/ && \
mv foo.c ~/bar/baz/

एक सरल स्क्रिप्ट इसे स्वचालित रूप से करने के लिए (अप्रयुक्त):

#!/bin/sh

# Grab the last argument (argument number $#)    
eval LAST_ARG=\$$#

# Strip the filename (if it exists) from the destination, getting the directory
DIR_NAME=`echo $2 | sed -e 's_/[^/]*$__'`

# Move to the directory, making the directory if necessary
mkdir -p "$DIR_NAME" || exit
mv "$@"

जब मैं "$ dirname ~? Bar / baz /" चलाता हूं, तो मुझे "/ home / dmckee / bar" मिलता है, जो कि यहां यो नहीं चाहते हैं ...
dmckee --- पूर्व-मध्यस्थ ने बिल्ली का बच्चा

@ मार्की, आह, आप सही हैं। इसे हल करने के बारे में कोई विचार? यदि आप इनपुट ~ / बार / baz आप या तो (ए) कॉपी करना चाहते हैं ~ / बार / और नाम बदलकर baz, या (b) कॉपी ~ / बार / baz /। नौकरी के लिए बेहतर उपकरण क्या है?
स्ट्रेजर

@dmckee, मैंने एक समाधान के साथ आने के लिए regexp / sed का उपयोग किया है। क्या यह आपकी पसंद के हिसाब से काम करता है? =]
स्ट्रैजर

अच्छा है, $ 2 को छोड़कर अंतिम तर्क नहीं है जब तक $ # = 2. मेरे पास एक कार्यक्रम नहीं है, ला, जो इसके अंतिम तर्क को छापता है। मैं इसे cp कमांड के एक संस्करण में उपयोग करता था (यदि वर्तमान तर्क को जोड़ने के लिए अंतिम निर्देशिका नहीं थी)। यहां तक ​​कि आधुनिक गोले भी $ 1 .. $ 9 का समर्थन करते हैं; एक पर्ल स्क्रिप्ट बेहतर हो सकती है।
जोनाथन लेफ़लर

@ लाइफ़लर, सच नहीं है - मुझे पता है कि बैश 9 से अधिक तर्कों का समर्थन करता है ($ {123} का उपयोग करना एक तरीका है)। मैं पर्ल को नहीं जानता, इसलिए खुद को जवाब देने के लिए स्वतंत्र महसूस करता हूं। =]
स्ट्रिंग

7

ऐसा लगता है कि जवाब नहीं है :)। मैं वास्तव में ऐसा करने के लिए केवल एक उपनाम या फंक नहीं बनाना चाहता, क्योंकि अक्सर यह एक-बंद होता है और मैं पहले से ही mvकमांड टाइप करने के बीच में हूं, लेकिन मुझे कुछ ऐसा मिला जो इसके लिए अच्छा काम करता है:

mv *.sh  shell_files/also_with_subdir/ || mkdir -p $_

यदि mvविफल रहता है (dir मौजूद नहीं है), यह निर्देशिका बना देगा (जो पिछले कमांड का अंतिम तर्क है, इसलिए ऐसा $_है)। तो बस इस कमांड को चलाएं, फिर upइसे फिर से चलाने के लिए, और इस समय mvको सफल होना चाहिए।


5

निम्नलिखित शेल स्क्रिप्ट, शायद?

#!/bin/sh
if [[ -e $1 ]]
then
  if [[ ! -d $2 ]]
  then
    mkdir --parents $2
  fi
fi
mv $1 $2

वह मूल हिस्सा है। आप तर्कों के लिए जाँच करने के लिए थोड़ा जोड़ना चाह सकते हैं, और आप चाहें तो व्यवहार बदल सकते हैं यदि गंतव्य मौजूद है, या स्रोत निर्देशिका मौजूद है, या मौजूद नहीं है (अर्थात ऐसा कुछ न लिखें जो मौजूद न हो) ।


1
यदि निर्देशिका मौजूद नहीं है, तो आपके कोड के साथ, इस कदम का प्रदर्शन नहीं किया जाता है!
strager

1
और आप mkdir को "-p" ध्वज याद किया।
dmckee --- पूर्व-मध्यस्थ ने बिल्ली का बच्चा

यदि कोई निर्देशिका मौजूद नहीं है, तो इसे क्यों बनाएं यदि आप इसे स्थानांतरित करने जा रहे हैं? (-पी झंडा तय)
क्रिस लुत्ज

मेरा मतलब है, जब आप स्क्रिप्ट चलाते हैं और डायरेक्टरी $ 2 मौजूद नहीं है, तो यह बनाई जाती है, लेकिन फाइल कॉपी नहीं होती है।
प्रात

उन्होंने एक सरल निर्माण दिया और जानकारी दी कि इसका विस्तार कैसे किया जाना चाहिए। क्यों इसे नीचे वोट ?!
ypnos

5

rsync आदेश चाल कर सकते हैं केवल यदि पिछले निर्देशिका गंतव्य पथ में मौजूद नहीं है, जैसे गंतव्य पथ के लिए ~/bar/baz/करता है, तो barमौजूद है, लेकिन bazनहीं, तो निम्न आदेश इस्तेमाल किया जा सकता है:

rsync -av --remove-source-files foo.c ~/bar/baz/

-a, --archive               archive mode; equals -rlptgoD (no -H,-A,-X)
-v, --verbose               increase verbosity
--remove-source-files   sender removes synchronized files (non-dir)

bazयदि यह मौजूद नहीं है तो इस मामले में डायरेक्टरी बनाई जाएगी। लेकिन अगर दोनों barऔर bazrsync मौजूद नहीं हैं, तो यह विफल हो जाएगा:

sending incremental file list
rsync: mkdir "/root/bar/baz" failed: No such file or directory (2)
rsync error: error in file IO (code 11) at main.c(657) [Receiver=3.1.2]

तो मूल रूप से इसके rsync -av --remove-source-filesलिए एक उपनाम के रूप में उपयोग करना सुरक्षित होना चाहिए mv


4

ऐसा करने का सबसे सरल तरीका है:

mkdir [directory name] && mv [filename] $_

मान लें कि मैंने अपनी डाउनलोड निर्देशिका ( ~/download) में स्थित पीडीएफ फाइलें डाउनलोड की हैं और मैं उन सभी को एक निर्देशिका में स्थानांतरित करना चाहता हूं जो मौजूद नहीं है (चलो कहते हैं)my_PDF )।

मैं निम्नलिखित कमांड टाइप करूँगा (सुनिश्चित करें कि मेरी वर्तमान कार्यशील निर्देशिका है ~/download):

mkdir my_PDF && mv *.pdf $_

यदि आप इस तरह से उपनिर्देशिका बनाना चाहते हैं तो आप -pविकल्प जोड़ सकते हैं mkdir: (माना जाता है कि मैं एक उपनिर्देशिका बनाना चाहता हूँ python):

mkdir -p my_PDF/python && mv *.pdf $_

2

Sillier, लेकिन काम करने का तरीका:

mkdir -p $2
rmdir $2
mv $1 $2

एक अस्थायी निर्देशिका सहित mkdir -p के साथ निर्देशिका बनाएं, जो गंतव्य फ़ाइल नाम को साझा करता है, फिर एक साधारण rmdir के साथ उस फ़ाइल नाम निर्देशिका को हटा दें, फिर अपनी फ़ाइल को उसके नए गंतव्य पर ले जाएं। मुझे लगता है कि dirname का उपयोग करने का उत्तर संभवतः सबसे अच्छा है।


येप, थोरा मूर्खतापूर्ण। :-) यदि $ 2 एक निर्देशिका है (जैसा मूल प्रश्न में है) तो यह बुरी तरह से विफल हो जाता है, क्योंकि अंतिम निर्देशिका हटा दी जाएगी, इसलिए 'mv' विफल हो जाएगा। और अगर $ 2 पहले से मौजूद है तो इसे हटाने की भी कोशिश करता है।
21

धन्यवाद! यह वही है जो मुझे पूरा करने के लिए आवश्यक है: mv ./old ./subdir/new जहां उप में अभी तक मौजूद नहीं है
माइक मुर्रे


1

कोड:

if [[ -e $1 && ! -e $2 ]]; then
   mkdir --parents --verbose -- "$(dirname -- "$2")"
fi
mv --verbose -- "$1" "$2"

उदाहरण:

तर्क: "d1" "d2 / उप"

mkdir: created directory 'd2'
renamed 'd1' -> 'd2/sub'

1

यह मूल निर्देशिका के साथ foo.cनई निर्देशिका में स्थानांतरित हो जाएगा ।bazbar

mv foo.c `mkdir -p ~/bar/baz/ && echo $_`

आवश्यकतानुसार मध्यवर्ती निर्देशिकाएँ बनाने का -pविकल्प mkdir
के बिना-pपथ में सभी निर्देशिकाओं के उपसर्ग पहले से मौजूद होना चाहिए।

बैकटिक्स के अंदर सब कुछ ``निष्पादित होता है और आउटपुट आपके कमांड के हिस्से के रूप में इन-लाइन में वापस आ जाता है।
चूंकि mkdirकुछ भी वापस नहीं आता है, केवल आउटपुट echo $_को कमांड में जोड़ा जाएगा।

$_पहले निष्पादित कमांड के अंतिम तर्क का संदर्भ देता है।
इस स्थिति में, यह आपकी नई निर्देशिका ( ~/bar/baz/) को दिए गए पथ को वापस कर देगाmkdir कमांड ।


मैंने एक गंतव्य को दिए बिना एक संग्रह को अनज़िप कर दिया और demo-app.zipअपनी वर्तमान निर्देशिका को छोड़कर सभी फाइलों को एक नई निर्देशिका में स्थानांतरित करना चाहा demo-app
निम्नलिखित लाइन चाल है:

mv `ls -A | grep -v demo-app.zip` `mkdir -p demo-app && echo $_`

ls -Aछिपी हुई फ़ाइलों सहित सभी फ़ाइल नाम लौटाता है ( निहित के अलावा .और.. )।

पाइप प्रतीक |का उपयोग lsकमांड के आउटपुट grep( एक कमांड-लाइन, सादा-पाठ खोज उपयोगिता ) को पाइप करने के लिए किया जाता है । ध्वज को निर्देश खोजने के लिए और सभी फ़ाइल नाम को छोड़कर वापस जाने के लिए । फ़ाइलों की उस सूची को कमांड कमांड में जोड़ा जाता है, जो कि कमांड कमांड में ले जाए जाते हैं । लक्ष्य तर्क नई निर्देशिका का उपयोग करने और आउटपुट का उपयोग करने के लिए पारित करने का मार्ग है ।
-vgrepdemo-app.zip
mvmkdir$_echo


1
यह विवरण और स्पष्टीकरण का एक अच्छा स्तर है- और विशेष रूप से पहली पोस्ट के लिए। धन्यवाद!
जेरेमी कैनी

शुक्रिया, @JeremyCaney! मैं बाहर मदद शुरू करने के लिए उत्साहित हूँ!
इवान वंडर

0

आप ब्रेस एक्सटेंशन का उपयोग भी कर सकते हैं:

mkdir -p directory{1..3}/subdirectory{1..3}/subsubdirectory{1..2}      
  • जो 3 डायरेक्टरी (डायरेक्टरी 1, डायरेक्टरी 2, डायरेक्टरी 3) बनाता है,
    • और उनमें से प्रत्येक में दो उपनिर्देशिका (उपनिर्देशिका 1, उपनिर्देशिका 2),
      • और उनमें से प्रत्येक में दो उप-उपनिर्देशिकाएं (सबसुबोन्टी 1 और सबसुबोन्टी 2)।

आपको बैश 3.0 या नए का उपयोग करना होगा।


5
दिलचस्प है, लेकिन ओपी के सवाल का जवाब नहीं है।
एलेक्सी फेल्डेन्गलर

0
$what=/path/to/file;
$dest=/dest/path;

mkdir -p "$(dirname "$dest")";
mv "$what" "$dest"

1
इसे स्टैंडअलोन श स्क्रिप्ट बनाने के लिए, बस $
डे

0

मेरा एक स्ट्रिंग समाधान:

test -d "/home/newdir/" || mkdir -p "/home/newdir/" && mv /home/test.txt /home/newdir/

0

आप कमांड को चेन कर सकते हैं: mkdir ~/bar/baz | mv foo.c ~/bar/baz/
या शेल स्क्रिप्ट यहां है:

#!/bin/bash
mkdir $2 | mv $1 $2

1. किसी भी टेक्स्ट एडिटर को खोलें
2. कॉपी-पेस्ट शेल स्क्रिप्ट।
3. इसे mkdir_mv.sh के रूप में सहेजें
4. अपनी स्क्रिप्ट की निर्देशिका दर्ज करें: cd your/script/directory
5. फ़ाइल मोड बदलें : chmod +x mkdir_mv.sh
6. उपनाम सेट करें : alias mv="./mkdir_mv.sh"
अब, जब भी आप कमांड mvचलते निर्देशिका चलाते हैं तब मौजूद होगा यदि मौजूद नहीं है।


0

एक अन्य उत्तर में एक टिप्पणी के आधार पर, यहां मेरा शेल फ़ंक्शन है।

# mvp = move + create parents
function mvp () {
    source="$1"
    target="$2"
    target_dir="$(dirname "$target")"
    mkdir --parents $target_dir; mv $source $target
}

इसे .bashrc या इसी तरह शामिल करें ताकि आप इसे हर जगह उपयोग कर सकें।

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