फ़ोल्डर में हर png के लिए txt फ़ाइलें बनाना चाहते हैं


12

मेरे पास यह स्क्रिप्ट है

#!/bin/bash

folder='/home/data/mnist/training'

for filePng in $folder/*
do
touch $filePng.txt
done

यह काम करता है, बस, नाम वाली फ़ाइल के लिए 001.png, यह 001.png.txtइसके बजाय बनाता है 001.txt

मैं इसे कैसे संशोधित कर सकता हूं?


4
अपने चरों को उद्धृत करना एक अच्छी आदत है। शेल स्क्रिप्ट एक अजीब भाषा है जो समय के साथ-साथ पूरी तरह से गेट-गो से डिज़ाइन की जाती है, इसलिए दुर्भाग्य से कुछ कष्टप्रद चीजें जैसे कि आवश्यक हो जाती हैं। अपने चर को उद्धृत किए बिना, चर सामग्री में व्हॉट्सएप या तारांकन अजीब तरीके से चीजों को तोड़ देगा। अपनी स्क्रिप्ट को और अधिक मजबूत बनाने के लिए, हमेशा दोहरे चर वाले अपने चर का उपयोग करें। यहाँ, आप कहेंगे for filePng in "$folder"/*और touch "$filePng".txt - नोट करें कि आप उन्हें केवल तभी उद्धृत करेंगे जब एक से अधिक हो $
मुजेर

3
यह एक XY समस्या की तरह दिखता है ... आप ऐसा करने की कोशिश क्यों कर रहे हैं?
जेरोमेज

जवाबों:


16

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

touch "$folder/$(basename "$filePng" .png).txt"

अतिरिक्त नोट करें $folder/। यह नेक्सेसरी है क्योंकि बेसन कमांड से रास्ता निकालता है।


क्या मैं सुझाव दे सकता हूं कि आपने अपने पैरामीटर विस्तार और कमांड प्रतिस्थापन का हवाला दिया है?
टॉम फेनच

@TomFenech हाँ, शायद पूरे स्ट्रिंग को उद्धृत करने के लिए एक अच्छा विचार है। मैंने अपना उत्तर संपादित किया।
वेन_युक्स

मुझे यकीन नहीं है कि आपने भीतर के उद्धरण क्यों निकाले $filePng- वे भी उपयोगी थे।
टॉम फेनेच

1
नहीं, क्योंकि $( )एक नया उद्धरण संदर्भ स्थापित करता है।
टॉम फेनेच

2
ओह, आप सही कह रहे हैं - आज कुछ नया
सीखें

31

आप शेल के पैरामीटर विस्तार सुविधाओं का उपयोग करके मौजूदा एक्सटेंशन को हटा सकते हैं

${parameter%pattern}'पैटर्न' का मिलान 'पैरामीटर' के अंत से होता है। परिणाम 'पैरामीटर' का विस्तारित मान है जो सबसे कम मिलान हटा दिया गया है।

तो आपके मामले में, के $filePng.txtसाथ बदलें"${filePng%.png}.txt"


10

स्टीलड्राइवर में पहले से उल्लेखित पैरामीटर पैरामीटर के विस्तार के साथ - हम कार्य करने के लिए स्ट्रिंग प्रतिस्थापन का उपयोग कर सकते हैं। इसके अतिरिक्त, आपको चर का उद्धरण करना चाहिए। नीचे आपकी संपादित स्क्रिप्ट है।

#!/bin/bash

folder='/home/data/mnist/training'

for filePng in "$folder"/*
do
    touch "${filePng/.png/.txt}"
done

9

यदि आपके पास बनाने के लिए बहुत सारी फाइलें हैं, तो एक बार में एक से अधिक फाइल को "टच" करना सार्थक होगा, ताकि आपको उनमें से प्रत्येक के लिए एक नई प्रक्रिया को अपनाने की जरूरत न पड़े (जो कि कई बार किए जाने में काफी समय लेती है हजार बार)।

विकल्प 1: पैटर्न प्रतिस्थापन + xargs

यह विकल्प touchएक ही बार में कमांड को कई रास्तों की आपूर्ति करेगा , आमतौर पर कुछ हजार या जो भी सिस्टम एक एकल कमांड लाइन पर फिट हो सकता है।

find "$folder" -mindepth 1 -maxdepth 1 -name '*.png' -print0 |
sed -ze 's/\.png$/.txt/' |
xargs -r0 -- touch --

विकल्प 2: पैरामीटर विस्तार + कमांड आउटपुट पुनर्निर्देशन

यह विकल्प बिल्कुल नहीं चलता है touch, लेकिन इसके बजाय Bash / Bourne / POSIX शेल सुविधाओं का उपयोग करता है, जिसके लिए सब-प्रक्रियाओं की आवश्यकता नहीं होती है।

for f in "$folder"/*.png; do
    : >> "${f%.png}.txt"
done

4

यदि आपको विश्वास है कि आपके पास .pngनाम के बीच में कहीं फाइल नहीं है , तो आप पैरामीटर विस्तार के साथ एक सरणी का उपयोग कर सकते हैं:

pngs=( /path/to/pngs/*.png )
touch "${pngs[@]/.png/.txt}"

यह भंडार फ़ाइलों के अंत में करने के लिए सभी रास्ते .pngएक सरणी में और उसके बाद पैरामीटर विस्तार का उपयोग करता है की सूची बनाने के लिए .txt, फ़ाइलों प्रतिस्थापन .pngके लिए .txtहर एक पर।

इस बात को ध्यान में रखें कि यदि आपके पास इतनी सारी फाइलें हैं, तो वे एक ही आह्वान के तर्क के रूप में पारित नहीं हो सकती हैं touch

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