मैं सभी फाइलों पर एक विशिष्ट तरीके से सबफ़ोल्डर्स में एक सुरुचिपूर्ण तरीके से एक प्रदर्शन कैसे कर सकता हूं?


18

मेरा वर्तमान सर्वश्रेष्ठ दांव है:

for i in $(find . -name *.jpg); do echo $i; done

समस्या: फ़ाइल नाम में रिक्त स्थान नहीं संभालती है।

नोट: मुझे ऐसा करने का एक चित्रमय तरीका भी पसंद आएगा, जैसे कि "ट्री" कमांड।


आप बस के आसपास उद्धरण नहीं कर सकते $i? मैं ऐसा करता हूं और यह ठीक काम करता है। क्या उस दृष्टिकोण में कुछ गड़बड़ है?
उमर फारूक ख्वाजा

जवाबों:


26

विहित तरीका है

find . -name '*.jpg' -exec echo {} \;

(की जगह \;के साथ +करने के लिए एक से अधिक फ़ाइल पारित करने के लिए echoएक समय में)

या (जीएनयू विशिष्ट, हालांकि कुछ बीएसडी अब भी हैं):

find . -name '*.jpg' -print0 | xargs -r0 echo

zsh:

for i (**/*.jpg(D)) echo $i

2
यदि आप xargs -0 का उपयोग कर रहे हैं , तो आपको इसे -0 से
मिलाना

1
@ माइकलकॉर्जलिंग, कोई भी उद्धरण {} कोई फर्क नहीं पड़ता। {} खोज से विस्तारित होता है, शेल से नहीं। एक सुधार का उपयोग नहीं किया जाएगा echoजो \b( जैसे कम से कम यूनिक्स कंफर्मेंट echoएस) से बचने के दृश्यों का विस्तार करता है ।
स्टीफन चेज़लस

1
@ क्या आपको यकीन है? findमैनपेज शो find . -type f -exec file '{}' \;में EXAMPLESअनुभाग। शायद कुछ गोले ब्रेसिज़ का विशेष रूप से इलाज करेंगे।
QuasarDonkey

1
उद्धरण नुकसान नहीं करते हैं, लेकिन कोई फर्क नहीं पड़ता। सब के सब '{}', \{\}, {}, "{}", '{'}खोल (जो भी बॉर्न-जैसा शेल) द्वारा एक तर्क है कि दो अक्षर है खोजने के लिए "{" और "}" का विस्तार कर रहे हैं। "खोजो" को "प्रतिध्वनी खोजें" से बदलें, या printf '<%s>\n' findयदि आप डबल-चेक करना चाहते हैं।
स्टीफन चेजेलस


2

बेहतर जवाब पहले ही दिए जा चुके हैं।

लेकिन ध्यान दें कि आपके द्वारा दिए गए कोड में रिक्त स्थान एकमात्र समस्या नहीं है। टैब, न्यूलाइन और वाइल्डकार्ड वर्ण भी एक समस्या है।

साथ में

IFS='
'
set -f
for i in $(find . -name '*.jpg'); do echo "$i"; done

तब केवल न्यूलाइन वर्ण ही एक समस्या है।


1

आपने जो उल्लेख किया है, वह उन बुनियादी समस्याओं में से एक है, जिनका लोग सामना करते हैं, जब वे फ़ाइल नाम पढ़ने की कोशिश करते हैं। कभी-कभी, सीमित ज्ञान और फ़ाइल और फ़ोल्डर संरचना की गलत धारणा वाले लोग यह भूल जाते हैं कि " UNIX सब कुछ एक फ़ाइल है "। इसलिए वे यह नहीं समझते कि उन्हें रिक्त स्थान को संभालने की आवश्यकता है, क्योंकि फ़ाइल नाम में रिक्त स्थान के साथ 2 या अधिक शब्द हो सकते हैं।

समाधान: ऐसा करने का एक बेहतर ज्ञात तरीका यह है कि एक साफ पढ़ा जाए

हम यहां मौजूद सभी फाइलों को पढ़ेंगे और उन्हें एक चर में रखेंगे, अगली बार जब वांछित प्रसंस्करण करते हैं तो हमें बस उस चर को उद्धरणों के अंदर रखना होगा जो रिक्त स्थान के साथ फ़ाइल नामों को संरक्षित करेगा। यह इसे करने के मूल तरीकों में से एक है, हालांकि, अन्य लोगों द्वारा यहां दिए गए अन्य उत्तर बस के रूप में भी काम करते हैं।

SCRIPT:

 find /path/to/files/ -iname "*jpg" | \
  while read I; do
   cp -v --parent "$I" /backup/dir/
  done

यहाँ मैं उन्हें पथ देकर फाइलें पढ़ रहा हूं और जो कुछ भी मैं पढ़ रहा हूं, उन्हें एक चर के अंदर रख रहा हूं, जिसे मैं बाद में एक बिंदु पर उद्धृत करूंगा, ताकि रिक्त स्थान को संरक्षित करने के लिए इसे संसाधित किया जा सके।

आशा है कि यह आपको किसी तरह से मदद करेगा।


1
"सब कुछ एक फाइल है" कुछ और को संदर्भित करता है। आपका समाधान विशिष्ट है और फ़ाइल नाम में बैकस्लैश या न्यूलाइन वर्णों का सामना नहीं करता है। "पढ़ते समय" गोले (आईएमओ) में अक्सर खराब शेल स्क्रिप्टिंग अभ्यास का संकेत होता है।
स्टीफन चेजलस

@sch: हुह, और मैं सोचता था, यह ठीक है। यह इंगित करने के लिए धन्यवाद। मुझे शायद इसे और अधिक देखने की आवश्यकता है।
डार्क नाइट

क्षमा करें, मेरा मतलब "GNU" था, ऊपर "GUN" नहीं (यह पहली बार है जब मुझे एहसास हुआ कि ये लोग BTW हैं ...)
Stéphane Chazelas

1

बस के साथ findऔर bash:

find . -name '*.jpg' -exec bash -c '
    echo "treating file $1 in bash, from path : ${1%/*}" 
' -- {} \;

इस तरह, हम उपयोग करते हैं $1 बैश में , एक मूल स्क्रिप्ट की तरह, जो किसी भी उन्नत (या नहीं) कार्यों को करने के लिए अच्छा दृष्टिकोण खोलते हैं।

एक अधिक कुशल तरीका (हर फ़ाइल के लिए एक नया बैश शुरू करने से बचने के लिए):

find . -name '*.jpg' -exec bash -c 'for i do
    echo "treating file $i in bash, from path : ${i%/*}" 
  done' -- {} +

0

बैश के हालिया संस्करण में, आप globstarविकल्प का उपयोग कर सकते हैं :

shopt -s globstar
for file in **/*.jpg ; do
    echo "$file"
done

साधारण कार्यों के लिए, आप पूरी तरह से लूप छोड़ सकते हैं:

echo **/*.jpg

जबकि वह zsh में काम करता है (जहाँ से फीचर उत्पन्न हुआ है) और ksh93 के साथ (के साथ set -G), इसका उपयोग bash में नहीं किया जाना चाहिए क्योंकि bash संस्करण मूलभूत रूप से टूटा हुआ है (GNU की तरह grep -r) क्योंकि यह निर्देशिकाओं ( find -Lzsh या समकक्ष) के सहानुभूति में उतरता है ***/*.jpg)। यह भी ध्यान दें कि खोजने के विपरीत, यह डॉटफ़िल्स को ommit करेगा और dotdirs में नहीं उतरेगा (डिफ़ॉल्ट रूप से)।
स्टीफन चेज़लस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.