আমি কীভাবে নীচের বিন্যাসে একটি ডিরেক্টরি সমতল করতে পারি?
আগে: ./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
উভয় বিদ্যমান। আমি ধরে নিচ্ছি আপনি কি আগেরটির সাথে প্রতিস্থাপন করতে চান না?
উত্তর:
সতর্কতা: আমি এই কমান্ডগুলির বেশিরভাগ সরাসরি আমার ব্রাউজারে টাইপ করেছি। ক্যাভেট লেক্টর।
zmv -o -i -Qn '(**/)(*)(D)' '${1//\//-}$2'
ব্যাখ্যা: প্যাটার্নটি **/*
বর্তমান ডিরেক্টরিটির সাব-ডিরেক্টরিতে সমস্ত ফাইলের সাথে পুনরাবৃত্তভাবে মিলছে (এটি বর্তমান ডিরেক্টরিতে ফাইলগুলির সাথে মেলে না, তবে এগুলির নতুন নামকরণের প্রয়োজন নেই)। প্রথম দুটি জোড়া বন্ধনী হ'ল এমন গোষ্ঠী যা প্রতিস্থাপনের পাঠ্য হিসাবে $1
এবং হিসাবে উল্লেখ করা যেতে পারে $2
। চূড়ান্ত যুগল বন্ধনীগুলি গ্লোব D
কোয়ালিফায়ার যুক্ত করে যাতে ডট ফাইলগুলি বাদ না যায়। -o -i
এর অর্থ -i
বিকল্পটি পাস করার অর্থ mv
একটি বিদ্যমান ফাইলটি ওভাররাইট করা হলে আপনাকে অনুরোধ জানানো হবে।
কেবল পসিক্স সরঞ্জাম সহ:
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 … +
(ওপেনবিএসডি, আমি আপনাকে দেখছি):
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
কি আসলে এটি করতে পারে (দৃust়ভাবে)?"
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
পরিবেশের পরিবর্তনশীল বিন্দুটি হারিয়েছেন যা প্রতিটি ইউনিক্স সিস্টেম ব্যবহার করে uses আপনি যদি লিখেন /bin/find
তবে আপনার স্ক্রিপ্টটি আসলে প্রতিটি সিস্টেমে (গিলস, আমার, এবং সম্ভবত ওপি'র) টিতে নষ্ট হয়ে গেছে /bin/find
(যেমন বি / সি এটিতে রয়েছে /usr/bin/find
)। PATH
পরিবেশের পরিবর্তনশীলের পুরো পয়েন্টটি এটি একটি নন-ইস্যু করা।
$(pwd)
ইতিমধ্যে একটি পরিবর্তনশীল উপলব্ধ: $PWD
। তবে আপনাকে অবশ্যই এখানে একটি নিখুঁত পাথ ব্যবহার করা উচিত নয় : যদি আপনার স্ক্রিপ্টটি এখান থেকে বলা হয়, বলুন /home/tim
, এটি নামকরণের চেষ্টা /home/tim/some/path
করে /home-tim-some-path
।