मैं निम्नलिखित प्रारूप में एक निर्देशिका को कैसे समतल कर सकता हूं?
इससे पहले: ./aaa/bbb/ccc.png
उपरांत: ./aaa-bbb-ccc.png
./foo/bar/baz.pngऔर ./foo-bar-baz.pngदोनों मौजूद हैं। मुझे लगता है कि आप बाद वाले को पूर्व से बदलना नहीं चाहते हैं?
मैं निम्नलिखित प्रारूप में एक निर्देशिका को कैसे समतल कर सकता हूं?
इससे पहले: ./aaa/bbb/ccc.png
उपरांत: ./aaa-bbb-ccc.png
./foo/bar/baz.pngऔर ./foo-bar-baz.pngदोनों मौजूद हैं। मुझे लगता है कि आप बाद वाले को पूर्व से बदलना नहीं चाहते हैं?
जवाबों:
चेतावनी: मैंने इनमें से अधिकांश कमांड सीधे अपने ब्राउज़र में टाइप किए। कैवेट लेक्टर।
Zsh और zmv के साथ :
zmv -o -i -Qn '(**/)(*)(D)' '${1//\//-}$2'
स्पष्टीकरण: पैटर्न **/*वर्तमान निर्देशिका की उपनिर्देशिकाओं में सभी फ़ाइलों से मेल खाता है, पुनरावर्ती रूप से (यह वर्तमान निर्देशिका में फ़ाइलों से मेल नहीं खाता है, लेकिन इनका नाम बदलने की आवश्यकता नहीं है)। कोष्ठक के पहले दो जोड़े ऐसे समूह हैं जिन्हें प्रतिस्थापन पाठ के रूप में $1और संदर्भित किया जा सकता है $2। कोष्ठक की अंतिम जोड़ी D ग्लोब क्वालीफायर को जोड़ती है ताकि डॉट फाइलें लोप न हों। विकल्प -o -iको पास करने का मतलब है ताकि आपको संकेत -iदिया mvजाए कि क्या कोई मौजूदा फ़ाइल अधिलेखित की जाएगी।
केवल POSIX टूल के साथ:
find . -depth -exec sh -c '
for source; do
case $source in ./*/*)
target="$(printf %sz "${source#./}" | tr / -)";
mv -i -- "$source" "${target%z}";;
esac
done
' _ {} +
स्पष्टीकरण: caseकथन वर्तमान निर्देशिका और वर्तमान निर्देशिका के शीर्ष-स्तरीय उपनिर्देशिकाओं को छोड़ देता है। targetस्रोत फ़ाइल नाम शामिल है ( $0) प्रमुख ./छीन लिया और डैश के साथ सभी स्लैशों के साथ, एक अंतिम z। zयदि फ़ाइल नाम एक नई सीमा के साथ समाप्त होता है, तो अंतिम होता है: अन्यथा कमांड प्रतिस्थापन इसे बंद कर देगा।
यदि आपका findसमर्थन नहीं करता है -exec … +(OpenBSD, मैं आपको देख रहा हूं):
find . -depth -exec sh -c '
case $0 in ./*/*)
target="$(printf %sz "${0#./}" | tr / -)";
mv -i -- "$0" "${target%z}";;
esac
' {} \;
बैश (या ksh93) के साथ, आपको डैश द्वारा स्लैश को बदलने के लिए किसी बाहरी कमांड को कॉल करने की आवश्यकता नहीं है, आप स्ट्रिंग प्रतिस्थापन निर्माण के साथ ksh93 पैरामीटर विस्तार का उपयोग कर सकते हैं ${VAR//STRING/REPLACEMENT}:
find . -depth -exec bash -c '
for source; do
case $source in ./*/*)
source=${source#./}
target="${source//\//-}";
mv -i -- "$source" "$target";;
esac
done
' _ {} +
for sourceउदाहरण पहले प्रस्तुत फ़ाइल / dir याद आती है ... मैं अंत में पता चला गया है तुम क्यों (सामान्य रूप से) का इस्तेमाल किया है _के रूप में $0महान जवाब के लिए धन्यवाद :) ... और। मैं उनसे बहुत कुछ सीखता हूं।
जबकि यहाँ पहले से ही अच्छे उत्तर हैं, मुझे यह अधिक सहज लगता है, भीतर bash:
find aaa -type f -exec sh -c 'new=$(echo "{}" | tr "/" "-" | tr " " "_"); mv "{}" "$new"' \;
aaaआपकी मौजूदा निर्देशिका कहां है इसमें मौजूद फ़ाइलों को वर्तमान निर्देशिका में ले जाया जाएगा (केवल आहा में खाली निर्देशिकाओं को छोड़कर)। दोनों कॉल trदोनों निर्देशिकाओं और रिक्त स्थान को संभालने के लिए (बच गए स्लैश के लिए तर्क के बिना - पाठक के लिए एक व्यायाम)।
मैं इसे अधिक सहज और अपेक्षाकृत आसान मानता हूं। यानी मैं findमापदंडों को बदल सकता हूं अगर मैं केवल .png फ़ाइलों को ढूंढना चाहता हूं। मैं trकॉल बदल सकता हूं , या आवश्यकतानुसार जोड़ सकता हूं । और मैं echoइससे पहले जोड़ सकता हूं mvअगर मैं नेत्रहीन जांच करना चाहता हूं कि यह सही काम करेगा (तब अतिरिक्त के बिना दोहराएं echoयदि चीजें सही दिखती हैं:
find aaa -name \*.png -exec sh -c 'new=$(echo "{}" | tr "/" "-" | tr " " "_"); echo mv "{}" "$new"' \;
ध्यान दें कि मैं उपयोग कर रहा हूं find aaa... और find .... या find aaa/... जैसा कि बाद के दो अंतिम फ़ाइल नाम में अजीब कलाकृतियों को छोड़ देगा।
find . -mindepth 2 -type f -name '*' |
perl -l000ne 'print $_; s/\//-/g; s/^\.-/.\// and print' |
xargs -0n2 mv
नोट: यह फ़ाइल नाम के लिए काम नहीं करेगा जिसमें शामिल हैं \n।
यह जाहिर है केवल प्रकार से चलता है fफ़ाइलें ...
केवल नाम संघर्ष फाइलों से होगा में पहले से मौजूद लोक निर्माण विभाग
इस मूल उपसमूह के साथ परीक्षण किया गया
rm -fr junk
rm -f junk*hello*
mkdir -p junk/junkier/junkiest
touch 'hello hello'
touch 'junk/hello hello'
touch 'junk/junkier/hello hello'
touch 'junk/junkier/junkiest/hello hello'
जिसके परिणामस्वरूप
./hello hello
./junk-hello hello
./junk-junkier-hello hello
./junk-junkier-junkiest-hello hello
यहाँ एक lsसंस्करण है .. टिप्पणियाँ स्वागत है। यह इस तरह के अजीब फ़ाइलनाम के लिए काम करता है
"j1ळ\n\001\n/j2/j3/j4/\nh h\n", लेकिन मैं वास्तव में किसी भी नुकसान के बारे में जानना चाहता हूं। यह " lsवास्तव में दुर्भावनापूर्ण रूप से ऐसा कर सकता है ?"
ls -AbQR1p * | # paths in "quoted" \escaped format
sed -n '/":$/,${/.[^/]$/p}' | # skip files in pwd, blank and dir/ lines
{ bwd="$PWD"; while read -n1; # save base dir strip leading "quote
read -r p; do # read path
printf -vs "${p%\"*}" # strip trailing quote"(:)
[[ $p == *: ]] && { # this is a directory
cd "$bwd/$s" # change into new directory
rnp="${s//\//-}"- # relative name prefix
} || mv "$s" "$bwd/$rnp$s"
done; }
बस trकमांड के लिए फ़ाइल नाम + पथ को पाइप करें ।tr <replace> <with>
for FILE in `find aaa -name "*.png"`
do
NEWFILE=`echo $FILE | tr '/' '-'`
cp -v $FILE $NEWFILE
done
cpकरने के लिए लाइन बदलना होगा cp -v "$FILE" "$NEWFILE"? (इसके अलावा, आपको केवल पीएनजी फाइलें नहीं माननी चाहिए।)
cpलाइन में उद्धरण जोड़ना अपर्याप्त है। लूप के findसाथ पार्सिंग आउटपुट का संपूर्ण दृष्टिकोण forत्रुटिपूर्ण है। उपयोग करने के लिए केवल सुरक्षित तरीके findहैं -exec, या -print0यदि उपलब्ध हो (कम से कम पोर्टेबल -exec)। मैं एक और अधिक मजबूत विकल्प का सुझाव देता हूं, लेकिन आपका प्रश्न फिलहाल निर्दिष्ट है।
फ़ाइल नाम में रिक्त स्थान के लिए सुरक्षित:
#!/bin/bash
/bin/find $PWD -type f | while read FILE
do
_new="${FILE//\//-}"
_new="${_new:1}"
#echo $FILE
#echo $_new
/bin/mv "$FILE" "$_new"
done
स्पष्ट कारणों के cpबजाय के साथ खदान mv, लेकिन उसी का उत्पादन करना चाहिए।
type find-> find is /usr/bin/findमेरी मशीन पर। PATHएक स्क्रिप्ट में एक चर नाम के रूप में उपयोग करना एक भयानक विचार है। इसके अलावा, आपकी स्क्रिप्ट रिक्त स्थान या बैकस्लैश के साथ नाम दर्ज करती है, क्योंकि आप readकमांड का दुरुपयोग करते हैं (इस साइट को खोजें IFS read -r)।
find is hashed (/bin/find), प्रासंगिक कैसे? अलग डिस्ट्रॉर्स अलग हैं?
PATHपर्यावरण चर के बिंदु को याद कर रहे हैं , जो कि हर यूनिक्स प्रणाली का उपयोग करता है। यदि आप लिखते हैं, /bin/findतो आपकी स्क्रिप्ट वास्तव में हर सिस्टम पर टूटी हुई है (गिल्स, मेरा, और शायद ओपी का) जो नहीं है /bin/find(जैसे b / c यह है /usr/bin/find)। PATHपर्यावरण चर का पूरा बिंदु इसे गैर-मुद्दा बनाना है।
$(pwd)पहले से ही एक चर में उपलब्ध है $PWD:। लेकिन आपको यहां एक निरपेक्ष पथ का उपयोग नहीं करना चाहिए : यदि आपकी स्क्रिप्ट को कहा जाता है /home/tim, तो इसका नाम बदलने /home/tim/some/pathका प्रयास किया जाता है /home-tim-some-path।