आप एक डायरेक्टरी से दूसरी डायरेक्टरी में (छिपी सहित) सभी फाइलों को कैसे स्थानांतरित करते हैं?


132

मैं एक निर्देशिका (छिपी हुई सहित) में सभी फाइलों को दूसरी निर्देशिका में कैसे स्थानांतरित करूं?

उदाहरण के लिए, यदि मेरे पास ".hidden" और "notHidden" फ़ाइलों के साथ एक फ़ोल्डर "फू" है, तो मैं दोनों फ़ाइलों को "बार" नामक निर्देशिका में कैसे स्थानांतरित करूं? निम्नलिखित काम नहीं करता है, क्योंकि ".hidden" फ़ाइल "फू" में रहती है।

mv Foo/* Bar/

इसे स्वयं आज़माएं।

mkdir Foo
mkdir Bar
touch Foo/.hidden
touch Foo/notHidden
mv Foo/* Bar/


बाह, मुझे पता था कि मुझे टाइप करने से पहले जवाबों को ताज़ा करना चाहिए था। बहुत ही उपयोगी लिंक।
स्टीवन डी

दुख की बात है, इस सवाल को यहां समाप्त हो गया क्योंकि मैं इतने पर कहा कि इसे यहाँ बढ़ना चाहिए या SU, निश्चित रूप से तो यह यहां ले जाया जब वहाँ SU पर डुप्लिकेट था पहले से ही :)
माइकल Mrozek

व्यक्तिगत रूप से, मुझे लगता है कि एसयू पर * निक्स विशिष्ट प्रश्न और उत्तर ऑफ-टॉपिक होना चाहिए। वर्तमान नियमों के साथ हम दोनों के बीच सामग्री टकराव के टन के साथ समाप्त होते हैं - इस प्रश्न की तरह।
कोरी क्लेन

जवाबों:


151

Zsh

mv Foo/*(DN) Bar/

या

setopt -s glob_dots
mv Foo/*(N) Bar/

( (N)यदि आप जानते हैं कि निर्देशिका खाली नहीं है तो बाहर छोड़ दें ।)

दे घुमा के

shopt -s dotglob nullglob
mv Foo/* Bar/

Ksh93

यदि आप जानते हैं कि निर्देशिका खाली नहीं है:

FIGNORE='.?(.)'
mv Foo/* Bar/

मानक (POSIX) श

for x in Foo/* Foo/.[!.]* Foo/..?*; do
  if [ -e "$x" ]; then mv -- "$x" Bar/; fi
done

यदि आप mvकमांड को त्रुटि स्थिति में वापस आने देने के लिए तैयार हैं , भले ही वह सफल हो, यह बहुत आसान है:

mv Foo/* Foo/.[!.]* Foo/..?* Bar/

जीएनयू खोजें और जीएनयू एम.वी.

find Foo/ -mindepth 1 -maxdepth 1 -exec mv -t Bar/ -- {} +

मानक खोजें

यदि आपको स्रोत निर्देशिका में परिवर्तन करने में कोई आपत्ति नहीं है:

cd Foo/ &&
find . -name . -o -exec sh -c 'mv -- "$@" "$0"' ../Bar/ {} + -type d -prune

यह नियंत्रित करने के बारे में अधिक विवरण है कि क्या डॉट फाइलें bash, ksh93 और zsh में मेल खाती हैं।

दे घुमा के

dotglobविकल्प सेट करें ।

$ echo *
none zero
$ shopt -s dotglob
$ echo *
..two .one none zero

वहाँ भी अधिक लचीला GLOBIGNOREचर है , जिसे आप अनदेखा करने के लिए वाइल्डकार्ड पैटर्न की एक अलग-अलग सूची में सेट कर सकते हैं। यदि unset (डिफ़ॉल्ट सेटिंग), शेल ऐसा व्यवहार करता है मानो यदि dotglobसेट किया गया था तो मान रिक्त था , और मान .*मानें कि यदि विकल्प उपलब्ध नहीं है। मैनुअल में फाइलनाम विस्तार देखें । जब तक पैटर्न द्वारा स्पष्ट रूप से मिलान नहीं किया जाता है, तब तक व्यापक निर्देशिकाएं .और ..हमेशा छोड़ी जाती हैं .

$ GLOBIGNORE='n*'
$ echo *
..two .one zero
$ echo .*
..two .one
$ unset GLOBIGNORE
$ echo .*
. .. ..two .one
$ GLOBIGNORE=.:..
$ echo .*
..two .one

Ksh93

FIGNOREचर सेट करें । यदि unset (डिफ़ॉल्ट सेटिंग), शेल मान के रूप में व्यवहार करता है .*। उपेक्षा करने के लिए .और .., उन्हें स्पष्ट रूप से मिलान किया जाना चाहिए (ksh 93s + 2008-01-31 में मैनुअल बताता है कि .और ..हमेशा अनदेखा किया जाता है, लेकिन यह वास्तविक व्यवहार का सही वर्णन नहीं करता है)।

$ echo *
none zero
$ FIGNORE='@(.|..)'
$ echo *
..two .one none zero
$ FIGNORE='n*'
$ echo *
. .. ..two .one zero

आप उन्हें स्पष्ट रूप से मिलान करके एक पैटर्न में डॉट फाइलें शामिल कर सकते हैं ।

$ unset FIGNORE
$ echo @(*|.[^.]*|..?*)
..two .one none zero

यदि निर्देशिका खाली है, तो विस्तार खाली है, Nपैटर्न मिलान विकल्प का उपयोग करें : ~(N)@(*|.[^.]*|..?*)या ~(N:*|.[^.]*|..?*)

Zsh

dot_globविकल्प सेट करें ।

% echo *
none zero
% setopt dot_glob
% echo *
..two .one none zero

.और ..कभी भी मिलान नहीं किया जाता है, भले ही पैटर्न .स्पष्ट रूप से अग्रणी से मेल खाता हो ।

% echo .*
..two .one

आप D ग्लोब क्वालिफायर के साथ एक विशिष्ट पैटर्न में डॉट फाइलें शामिल कर सकते हैं ।

% echo *(D)
..two .one none zero

Nएक खाली निर्देशिका में विस्तार को खाली करने के लिए ग्लोब क्वालिफायर जोड़ें *(DN):।


नोट: यदि आप विभिन्न क्रम में फ़ाइल नाम विस्तार परिणाम (जैसे, मिल सकता है none, जिसके बाद .oneके बाद ..two) की अपनी सेटिंग के आधार पर LC_COLLATE, LC_ALLऔर LANGचर।


1
क्यों nullglob? यह mvकमांड को खत्म करने के लिए और अधिक समझ में आता है (जैसे मछली, csh / tsh, zsh (बिना (N)) do, या failglob के साथ बैश) mv /Bar/कमांड चलाने से कम अर्थ है।
स्टीफन चेज़लस

1
मैं कहूंगा कि आपका GLOBIGNORE वर्णन गलत और भ्रामक है। GLOBIGNORE को एक गैर-रिक्त मान पर सेट करना, dotglob को चालू करता है और बनाता है .और ..कभी भी मिलान नहीं किया जाता है (जैसे कि अन्य समझदार गोले जैसे कि zsh, मछली, pdksh और डेरिवेटिव) में भले ही आप dotglob को पीछे से बंद कर दें। ( GLOBIGNORE=:; shopt -u dotglob; echo .*आउटपुट नहीं होगा .और ..)। करने के लिए GLOBIGNORE स्थापित करने .:..या .या :एक ही प्रभाव है।
स्टीफन चेज़लस

ksh93हमेशा अनदेखी .और ..लगता है कि ksh93k+(जहां यह काम किया) और ksh93m(जहां यह अब काम नहीं करता है) के बीच में टूट गया है । ध्यान दें कि इसमें बुरा है कि ksh93पर्यावरण से FIGNORE का मूल्य लगेगा, इसलिए FIGNORE='!(..)'उदाहरण के लिए एक env var कहर पैदा कर सकता है।
स्टीफन चेजलस

24
#!/bin/bash

shopt -s dotglob
mv Foo/* Bar/

से man bash

डॉटग्लोब यदि सेट किया जाता है, तो बैश में '' से शुरू होने वाले फ़ाइल नाम शामिल होते हैं। pathname विस्तार के परिणामों में।


कैविएट के साथ कि यह कमांड एक त्रुटि कोड देता है यदि निर्देशिका खाली थी (भले ही कमांड वास्तव में इच्छित के रूप में प्रदर्शन किया हो)।
जिल्स

1
@ फिर, त्रुटि तब mvशिकायत से होगी कि उस फ़ाइल का नाम Foo/*मौजूद नहीं है। दिलचस्प है, अगर Fooखोज योग्य है, लेकिन पठनीय नहीं है, और वहाँ एक फ़ाइल है जिसे *वहां कहा जाता है, आपको कोई त्रुटि नहीं मिलेगी, उस फ़ाइल को स्थानांतरित कर दिया जाएगा, लेकिन निर्देशिका में अन्य नहीं। bashएक failglobविकल्प है इसलिए यह अधिक पसंद करता है zsh, fishया csh/ या tcshकमांड को एक त्रुटि के साथ निरस्त कर देता है जब ग्लोब को छोड़ने के उस संगीन व्यवहार के बजाय एक ग्लोब का विस्तार नहीं किया जा सकता है।
स्टीफन चेजलस

7

ऐसा करने का एक सरल तरीका bashहै

mv {Foo/*,Foo/.*} Bar/

लेकिन यह निर्देशिकाओं को भी स्थानांतरित करेगा।

यदि आप छिपी सहित सभी फ़ाइलों को स्थानांतरित करना चाहते हैं, लेकिन किसी भी निर्देशिका को स्थानांतरित नहीं करना चाहते हैं तो आप लूप और परीक्षण के लिए उपयोग कर सकते हैं।

for i in $(ls -d {Foo/*,Foo/.*});do test -f $i && mv -v $i Bar/; done;


4

उपयोग करने का एक तरीका है find:

find Foo/ -type f -exec mv -t Bar/ {} \+

-type fफ़ाइलें खोजने के लिए ढूंढें आदेश प्रतिबंधित करता है। आप जांच करनी चाहिए -type, -maxdepthऔर -mindepthके विकल्प findअपने आदेश खाते में उप निर्देशिकाओं के लिए अनुकूलित करने के लिए। ढूँढें का एक लंबा लेकिन बहुत ही उपयोगी मैनुअल पेज है


3
यह केवल नियमित फ़ाइलों को स्थानांतरित करता है Foo/, उपनिर्देशिकाओं और अन्य फ़ाइलों को नहीं।
जिल्स

2

प्रतिलिपि आदेश आज़माएँ cp:

$ cp -r myfolder/* destinationfolder

cp -r इसका मतलब है कि प्रतिलिपि पुनरावर्ती, इसलिए सभी फ़ोल्डर्स और फ़ाइलों की प्रतिलिपि बनाई जाएगी।

आप rmकिसी फ़ोल्डर को निकालने के लिए रिमूव कमांड का उपयोग कर सकते हैं :

$ rm -r myfolder

और देखें: सभी फाइलों को एक डायरेक्टरी से दूसरे में ले जाएं


2
जब आप बड़ी फ़ाइलों का एक बहुत आगे बढ़ रहे हैं, तो सबसे अच्छा नहीं है, लेकिन मुझे लगता है कि यह काम करेगा।
कोरी क्लेन

हो सकता है कि अगर आप स्टार की जगह डॉट का इस्तेमाल करें?
विन्सेन्ट

1

रुपीस एक और विकल्प है:

rsync -axvP --remove-source-files sourcedirectory/ targetdirectory

यह काम करता है क्योंकि rsync में अनुगामी स्लैश मामले हैं, sourcedirectory/निर्देशिका की सामग्री को संदर्भित करता है, जबकि sourcedirectoryनिर्देशिका स्वयं को संदर्भित करेगा।

इस पद्धति का नुकसान यह है कि rsync केवल इस कदम के बाद फ़ाइलों को साफ करेगा, निर्देशिका नहीं। तो आप एक खाली खट्टा पेड़ के साथ छोड़ दिया जाता है। इसके लिए वर्कअराउंड के लिए, देखें:

फ़ाइलें ले जाएँ और निर्देशिकाओं को rsync से हटाएं?

तो जबकि यह चाल परिचालन के लिए इष्टतम नहीं हो सकता है, यह प्रतिलिपि कार्यों के लिए अत्यंत उपयोगी हो सकता है।


1

बैश / मछली के लिए उत्तर

यहाँ वाइल्डकार्ड का उपयोग करने का एक तरीका दिया गया है:

.[!.]* ..?*से मेल खाएगी सभी छिपी हुई फ़ाइलें को छोड़कर .और..

.[!.]* ..?* *से मेल खाएगी सभी फाइलें (छुपा है या नहीं) को छोड़कर .और..

और इस प्रश्न के विशेष उदाहरण का उत्तर देने के लिए आपको आवश्यकता है cd foo && mv .[!.]* ..?* * ../bar

व्याख्या

.[!.]*एक-एक डॉट के साथ शुरू होने वाले फ़ाइल-नामों से मेल खाता है, इसके बाद किसी भी वर्ण के अलावा वैकल्पिक रूप से किसी भी स्ट्रिंग के बाद। यह काफी करीब है, लेकिन यह दो डॉट्स जैसी फाइलों से शुरू होता है ..foo। ऐसी फ़ाइलों को शामिल करने के लिए हम ..?*दो डॉट्स के साथ शुरू होने वाले फ़ाइल-नामों से मेल खाते हैं, इसके बाद किसी भी वर्ण, वैकल्पिक रूप से किसी भी स्ट्रिंग द्वारा पीछा किया जाता है।

परीक्षा

आप नीचे दिए गए आदेशों के साथ इन वाइल्डकार्ड का परीक्षण कर सकते हैं। मैंने उन्हें सफलतापूर्वक बैश और मछली के नीचे आज़माया है। वे श, zsh, xonsh के तहत असफल हो जाते हैं।

mkdir temp
cd temp
touch  a  .b  .bc  ..c  ..cd  ...d  ...de
ls .[!.]* ..?*
# you get this output:
          .b  .bc  ..c  ..cd  ...d  ...de
# cleanup
cd ..
rm -rf temp

0

आप चाल कमान के लिए फ़ाइलों का चयन करने के लिए backquotes के साथ मिल और grep करने में सक्षम हो सकते हैं। उन लोगों को एम.वी.

यानी छिपी हुई फाइलों के लिए

find Foo -maxdepth 1 | egrep '^Foo/[.]' # Output: .hidden

इसलिए

mv `find Foo -maxdepth 1 | egrep '^Foo/[.]'` Bar # mv Foo/.hidden Bar

केवल चयनित छुपी हुई फ़ाइलों को ले जाता है Bar:

mv `find Foo -maxdepth 1 | egrep '^Foo/.'` Bar # mv Foo/.hidden Foo/notHidden Bar

'के बाद से फू में सभी फ़ाइलों को ले जाता है।' जैसे egrep कमांड वर्गाकार कोष्ठक के बिना वाइल्डकार्ड के रूप में कार्य करता है।

^चरित्र मैच पंक्ति के आरंभ से शुरू होता है सुनिश्चित करता है।

egrepपैटर्न मिलान के कुछ विवरण यहां देखे जा सकते हैं

maxdepth 1स्टॉप का उपयोग उपनिर्देशिकाओं में जाने से मिलता है।


0

इस उत्तर से प्रेरित :

फाइलों को कॉपी किए बिना ...

rsync -ax --link-dest=../Foo/ Foo/ Bar

चेतावनियां:

  • --link-destपथ निरपेक्ष होना चाहिए या DESTINATION के सापेक्ष ( Bar उदाहरण में)

  • आपको /SOURCE ( Foo/उदाहरण में) के बाद रखना होगा, अन्यथा यह सामग्री की बजाय SOURCE फ़ोल्डर की प्रतिलिपि बना देगा।


0

मुझे लगता है कि यह बैश के लिए अच्छा काम करता है और शेल विकल्पों को बदलने की कोई आवश्यकता नहीं है

mv sourcedir/{*,.[^.]*} destdir/

संपादित करें:

इसलिए जैसा कि जी-मैन ने कहा, मेरा मूल उत्तर पॉज़िक्स कंप्लेंट नहीं है और एक बदलाव के साथ ndemou के उत्तर के रूप में बहुत समान है, जो कि स्ट्रिंग्स की सूची बनाने के लिए ब्रेस विस्तार का उपयोग करना है, जिस पर तब कार्रवाई की जाती है। इसका मतलब यह है कि आपको cdस्रोत निर्देशिका में जाने की आवश्यकता नहीं है । वास्तव में इतना बड़ा बदलाव नहीं, लेकिन यह अलग है।

उदाहरण: मान लीजिए कि आपके पास निम्नलिखित लेआउट पहले से हैं।

 $ tree -a
.
├── destdir
└── sourcedir
    ├── ..d1
    ├── ..d2
    ├── ..double
    ├── file-1
    ├── file-2
    ├── .hidden-1
    ├── .hidden-2
    ├── ...t1
    └── ...t2

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

mv sourcedir/{*,.[!.]*,..?*} destdir/

यह निम्नलिखित के लिए विस्तारित हो जाता है:

mv sourcedir/file-1 sourcedir/file-2 sourcedir/.hidden-1 sourcedir/.hidden-2 sourcedir/..d1 sourcedir/..d2 sourcedir/..double sourcedir/...t1 sourcedir/...t2 destdir/

अब आपको डेस्टिर में स्थित सभी फाइलों को देखना चाहिए :

 $ tree -a
.
├── destdir
   ├── ..d1
   ├── ..d2
   ├── ..double
   ├── file-1
   ├── file-2
   ├── .hidden-1
   ├── .hidden-2
   ├── ...t1
   └── ...t2
└── sourcedir

आप 4.x में और अधिक परिवर्धन के साथ बश में ब्रेसिज़ के साथ कुछ सुंदर शांत चीजें कर सकते हैं। की जाँच करें बैश-हैकर्स कुछ गंधा उदाहरण के लिए।


1
यह मूल रूप से ndemou के उत्तर को दोहराता है, सिवाय इसके कि आपने घुंघराले ब्रेसिज़ (उन्हें समझाए बिना) जोड़ा। लेकिन (1) आपका उत्तर उन फाइलों से मेल नहीं खाता है जिनके नाम के साथ शुरू होता है .., और (2) पोसिक्स का अनुपालन करने के लिए , आपको !इसके बजाय उपयोग करना चाहिए ^; यानी, {*,.[!.]*}
जी-मैन

@ जी-यार, इस बारे में खेद है। तो आप सही हैं और ndemou की प्रतिक्रिया नहीं देखने के लिए मेरा बुरा। वे बहुत ज्यादा एक ही बात कर रहे हैं। 1. मेरे संस्करण को इंगित करने के लिए धन्यवाद पॉज़िक्स आज्ञाकारी नहीं है। 2. मैं स्ट्रिंग्स की सूची बनाने के लिए ब्रेस विस्तार का उपयोग कर रहा हूं, जो शेल तब कार्रवाई करने के लिए उपयोग करेगा। इसका मतलब यह भी है कि मुझे cdफाइलों पर कार्रवाई करने के लिए स्रोत निर्देशिका में जाने की जरूरत नहीं है या सभी फाइलों के लिए पथों को व्यक्त करने के लिए एक ही फाइल पथों पर लिखना होगा। मैं किसी भी पाठक को इस बात की बेहतर तस्वीर देने के लिए शीघ्र ही उदाहरण प्रस्तुत करूंगा कि मैं किस बारे में बात कर रहा हूं।
cmndr sp0ck

0

के लिए कम से कम Linux distros, निम्नलिखित काम करने चाहिए। सबसे पहले, सभी एक मूल चाल करें (जो छिपी हुई फाइलों को याद करता है)। फिर, सब छिपा फ़ाइलों को स्थानांतरित (सहित .और ..जो होगा नहीं वास्तव में ले जाया जा)।

mv /sourceDir/* /destinationDir 2> /dev/null
mv /sourceDir/.* /destinationDir 2> /dev/null

नोट्स: यदि कोई दृश्य सामग्री नहीं है, तो पहला कमांड एक त्रुटि संदेश देगा। दूसरी कमांड हमेशा यह कहते हुए एक त्रुटि उत्पन्न करेगी कि यह स्थानांतरित नहीं हो सकता है .और ..। जैसे, त्रुटियों को ठीक करें /dev/null(जैसा दिखाया गया है)।

यदि आपको एक-लाइनर के रूप में इसकी आवश्यकता है, तो बस उन्हें अर्ध-बृहदान्त्र के साथ संयोजित करें:

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