دفعة إعادة تسمية الملفات مع باش
-
03-07-2019 - |
سؤال
كيف يمكن لـ Bash إعادة تسمية سلسلة من الحزم لإزالة أرقام إصداراتها؟لقد كنت ألعب مع كليهما expr
و %%
, ، ولكن دون جدوى.
أمثلة:
Xft2-2.1.13.pkg
يصبح Xft2.pkg
jasper-1.900.1.pkg
يصبح jasper.pkg
xorg-libXrandr-1.2.3.pkg
يصبح xorg-libXrandr.pkg
المحلول
هل يمكن استخدام المعلمة ميزة التوسع باش
for i in ./*.pkg ; do mv "$i" "${i/-[0-9.]*.pkg/.pkg}" ; done
وهناك حاجة ونقلت عن أسماء بمسافات.
نصائح أخرى
وإذا كان كل الملفات في نفس الدليل تسلسل
ls |
sed -n 's/\(.*\)\(-[0-9.]*\.pkg\)/mv "\1\2" "\1.pkg"/p' |
sh
وسوف القيام بعملك. و<م> ااا م> الأمر سيخلق سلسلة من ام م> الأوامر، والتي يمكن بعد ذلك الأنابيب في وعاء. فمن الأفضل لتشغيل أول خط أنابيب دون | sh
زائدة وذلك للتحقق من أن الأمر لا ما تريد.
لعنة من خلال الدلائل متعددة استخدام شيء من هذا القبيل
find . -type f |
sed -n 's/\(.*\)\(-[0-9.]*\.pkg\)/mv "\1\2" "\1.pkg"/p' |
sh
لاحظ أنه في ااا م> التعبير العادي تجميع التسلسل بين قوسين يسبقه مائل، \(
و\)
، بدلا من الأقواس واحدة (
و)
.
وسأفعل شيئا من هذا القبيل:
for file in *.pkg ; do
mv $file $(echo $file | rev | cut -f2- -d- | rev).pkg
done
ويفترض كل ما تبذلونه من الملفات الموجودة في الدليل الحالي. إن لم يكن، في محاولة لاستخدام تجد كما نصحت فوق خافيير.
تعديل : ل. أيضا، وهذه الصيغة لا تستخدم أي ميزات باش معين، كما فعل آخرون أعلاه، الذي يؤدي إلى مزيد من قابلية
وهنا هو POSIX شبه يعادل المقبولة حاليا الجواب . هذا الحرف الوحيد باش التوسع المعلمة ${variable/substring/replacement}
واحد والذي يتوفر في أي قذيفة بورن المتوافقة.
for i in ./*.pkg; do
mv "$i" "${i%-[0-9.]*.pkg}.pkg"
done
وو${variable%pattern}
التوسع المعلمة تنتج قيمة variable
مع أي لاحقة والذي يطابق pattern
إزالتها. (هناك ${variable#pattern}
أيضا لإزالة بادئة).
وظللت -[0-9.]*
subpattern من الإجابة مقبولة على الرغم من أنه ربما مضللة. انها ليست تعبير عادي، ولكن نمط غلوب. لذلك لا يعني "اندفاعة يليه صفر أو أكثر من أرقام أو النقاط". بدلا من ذلك، وهو ما يعني "اندفاعة، متبوعا برقم أو نقطة، تليها أي شيء". و"أي شيء" ستكون أقصر مباراة الممكنة، وليس أطول. (باش يقدم ##
و%%
لتقليم أطول بادئة المحتملة أو لاحقة، بدلا من أقصر).
وأفضل استخدام sed
لهذا، شيء من هذا القبيل:
find . -type f -name "*.pkg" |
sed -e 's/((.*)-[0-9.]*\.pkg)/\1 \2.pkg/g' |
while read nameA nameB; do
mv $nameA $nameB;
done
وكشف عن التعبير العادي ويترك باعتبارها ممارسة (كما هو التعامل مع أسماء الملفات التي تتضمن مسافات)
يمكننا أن نفترض sed
متوفر على أي *nix ، لكن لا يمكننا التأكد من دعمه sed -n
لتوليد أوامر mv.(ملحوظة: جنو فقط sed
يفعل هذا.)
ومع ذلك، يمكننا بسرعة إنشاء وظيفة الصدفة للقيام بذلك، باستخدام bash buildins وsed.
sedrename() {
if [ $# -gt 1 ]; then
sed_pattern=$1
shift
for file in $(ls $@); do
mv -v "$file" "$(sed $sed_pattern <<< $file)"
done
else
echo "usage: $0 sed_pattern files..."
fi
}
الاستخدام
sedrename 's|\(.*\)\(-[0-9.]*\.pkg\)|\1\2|' *.pkg
before:
./Xft2-2.1.13.pkg
./jasper-1.900.1.pkg
./xorg-libXrandr-1.2.3.pkg
after:
./Xft2.pkg
./jasper.pkg
./xorg-libXrandr.pkg
إنشاء المجلدات المستهدفة:
منذ mv
لا ينشئ المجلدات المستهدفة تلقائيًا لا يمكننا استخدام الإصدار الأولي الخاص بنا من sedrename
.
إنه تغيير بسيط إلى حد ما، لذا سيكون من الجيد تضمين هذه الميزة:
سنحتاج إلى وظيفة فائدة، abspath
(أو المسار المطلق) نظرًا لأن Bash لا يوجد لديه هذا البناء.
abspath () { case "$1" in
/*)printf "%s\n" "$1";;
*)printf "%s\n" "$PWD/$1";;
esac; }
بمجرد أن نتمكن من إنشاء المجلد (المجلد) المستهدف لنمط SED/RENAME الذي يتضمن بنية مجلد جديدة.
سيضمن هذا أننا نعرف أسماء المجلدات المستهدفة لدينا.عندما نعيد تسميته ، سنحتاج إلى استخدامه على اسم الملف الهدف.
# generate the rename target
target="$(sed $sed_pattern <<< $file)"
# Use absolute path of the rename target to make target folder structure
mkdir -p "$(dirname $(abspath $target))"
# finally move the file to the target name/folders
mv -v "$file" "$target"
إليك النص البرمجي الكامل للمجلد ...
sedrename() {
if [ $# -gt 1 ]; then
sed_pattern=$1
shift
for file in $(ls $@); do
target="$(sed $sed_pattern <<< $file)"
mkdir -p "$(dirname $(abspath $target))"
mv -v "$file" "$target"
done
else
echo "usage: $0 sed_pattern files..."
fi
}
بالطبع ، لا يزال يعمل عندما لا يكون لدينا مجلدات مستهدفة محددة أيضًا.
إذا أردنا وضع جميع الأغاني في مجلد، ./Beethoven/
نستطيع فعل ذلك:
الاستخدام
sedrename 's|Beethoven - |Beethoven/|g' *.mp3
before:
./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3
after:
./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3
جولة المكافأة...
استخدام هذا البرنامج النصي لنقل الملفات من المجلدات إلى مجلد واحد:
على افتراض أننا أردنا جمع جميع الملفات المتطابقة ، ووضعها في المجلد الحالي ، يمكننا القيام بذلك:
sedrename 's|.*/||' **/*.mp3
before:
./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3
after:
./Beethoven/ # (now empty)
./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3
ملاحظة على أنماط sed regex
تنطبق قواعد نمط SED العادية في هذا البرنامج النصي ، هذه الأنماط ليست PCRE (تعبيرات منتظمة متوافقة مع PERL).يمكن أن يكون لديك بناء جملة تعبير منتظم تم تمديده ، باستخدام أي منهما sed -r
أو sed -E
اعتمادا على النظام الأساسي الخاص بك.
انظر متوافق مع POSIX man re_format
للحصول على وصف كامل لأنماط regexp الأساسية والممتدة.
وأجد أن إعادة تسمية أداة أكثر وضوحا بكثير لاستخدام لهذا النوع من الشيء. لقد وجدت أنه في البيرة لOSX
وعلى سبيل المثال الخاص بك وأود أن تفعل:
rename 's/\d*?\.\d*?\.\d*?//' *.pkg
ووالصورة "تعني بديلا. النموذج ق / searchPattern / استبدال / files_to_apply. تحتاج إلى استخدام التعابير المنطقية لهذا الذي يأخذ دراسة صغيرة لكنها تستحق الجهد.
يبدو أن هذا يعمل على افتراض ذلك
- كل شيء ينتهي بـ $pkg
- يبدأ رقم الإصدار الخاص بك دائمًا بـ "-"
قم بإزالة .pkg، ثم قم بإزالة -..
for x in $(ls); do echo $x $(echo $x | sed 's/\.pkg//g' | sed 's/-.*//g').pkg; done
وكان لي الملفات *.txt
متعددة ليتم تسميتها .sql
في نفس المجلد.
أدناه عملت بالنسبة لي:
for i in \`ls *.txt | awk -F "." '{print $1}'\` ;do mv $i.txt $i.sql; done
وشكرا لك على هذه الأجوبة. كما أتيحت لي نوعا من المشكلة. نقل الملفات .nzb.queued إلى .nzb الملفات. وكان المساحات والعناصر غير المرغوب فيها الأخرى في أسماء الملفات وهذا حل مشكلتي:
find . -type f -name "*.nzb.queued" |
sed -ne "s/^\(\(.*\).nzb.queued\)$/mv -v \"\1\" \"\2.nzb\"/p" |
sh
وهو يقوم على إجابة لديوميديس سبينيليس.
والتعبير المعتاد يخلق مجموعة واحدة لاسم الملف بأكمله، ومجموعة واحدة بالنسبة للجزء قبل .nzb.queued ثم يخلق أمر قذيفة الخطوة. مع السلاسل نقلت. هذا يتجنب أيضا خلق حلقة في شيل لأن هذا ما يحدث بالفعل من خلال الحوار الاقتصادي الاستراتيجي.