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
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
回答:
あなたはbashのパラメータ拡張機能を使うことができます
for i in ./*.pkg ; do mv "$i" "${i/-[0-9.]*.pkg/.pkg}" ; done
スペースを含むファイル名には引用符が必要です。
rename "s/-[0-9.]*//" *.pkg
すべてのファイルが同じディレクトリにある場合、シーケンス
ls |
sed -n 's/\(.*\)\(-[0-9.]*\.pkg\)/mv "\1\2" "\1.pkg"/p' |
sh
あなたの仕事をします。sedのコマンドは、シーケンスを作成しますMV、コマンドこれを使用することができ、その後シェルにパイプ。最初に、末尾なしでパイプラインを実行することをお勧めします| shコマンドが望みどおりに機能することを確認するためにです。
複数のディレクトリを再帰するには、次のようなものを使用します
find . -type f |
sed -n 's/\(.*\)\(-[0-9.]*\.pkg\)/mv "\1\2" "\1.pkg"/p' |
sh
sedでは、正規表現のグループ化シーケンスは、単一の大括弧and ではなく、大括弧の前にバックスラッシュ\(and が続く ことに注意してください。\)()
lsスクリプトでは使用しないでください。最初の多様printf '%s\n' * | sed ...性は、いくつかの創造性で達成することができ、おそらくあなたもそれを取り除くことができsedます。Bashにprintfは、'%q'リテラルシェルメタキャラクターを含むファイル名がある場合に役立つフォーマットコードが用意されています。
私はこのようなことをします:
for file in *.pkg ; do
mv $file $(echo $file | rev | cut -f2- -d- | rev).pkg
done
すべてのファイルが現在のディレクトリにあると想定しています。そうでない場合は、上記のJavierのアドバイスに従ってfindを使用してください。
編集:また、このバージョンでは、他の上記のようにbash固有の機能を使用しないため、移植性が向上します。
以下は、現在受け入れられている回答に相当するPOSIX です。これは、Bashのみの${variable/substring/replacement}パラメーター拡張を、Bourne互換シェルで使用可能なパラメーター拡張と交換します。
for i in ./*.pkg; do
mv "$i" "${i%-[0-9.]*.pkg}.pkg"
done
パラメータ展開${variable%pattern}により、variable一致するすべての接尾辞がpattern削除された値が生成されます。(${variable#pattern}接頭辞を削除することもできます。)
-[0-9.]*誤解を招くかもしれませんが、私はサブパターンを受け入れられた回答から遠ざけました。これは正規表現ではなく、グロブパターンです。したがって、「ダッシュの後に0個以上の数字またはドットが続く」という意味ではありません。代わりに、「ダッシュの後に数字またはドットが続き、その後に何かが続く」ことを意味します。「何でも」は可能な最短の一致であり、最長ではありません。(バッシュの申し出##と%%かなり短いよりも、可能な限り最長の接頭辞または接尾辞をトリミングします。)
sed任意の* nixで使用できると想定できますが、sed -nmvコマンドの生成をサポートするかどうかはわかりません。(注:sedこれを行うのはGNUだけです。)
それでも、組み込みのbashと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。
これはかなり小さな変更なので、その機能を含めるとよいでしょう。
abspathbashにはこの機能が組み込まれていないため、ユーティリティ関数(または絶対パス)が必要です。
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パターンルールが適用されます。これらのパターンはPCRE(Perl互換の正規表現)ではありません。どちらsed -rかを使用するかsed -E
、プラットフォームに応じて、拡張正規表現構文をsedにすることができます。
man re_formatsedの基本および拡張正規表現パターンの詳細については、POSIX準拠を参照してください。
名前の変更は、この種のことを行うためのはるかに簡単なツールであることがわかりました。OSXのHomebrewで見つけました
あなたの例では、私はやります:
rename 's/\d*?\.\d*?\.\d*?//' *.pkg
「s」は代替を意味します。フォームはs / searchPattern / replacement / files_to_applyです。これには正規表現を使用する必要がありますが、少し勉強が必要ですが、努力する価値は十分あります。
forおよびsedなど細かいですが、それだけで使用することに速くずっと簡単だとrenameあなた自身が、多くの場合、これをやって見つければ。
renameコマンドがあるわけではありません。さらに、機能、構文、オプションが異なる renameコマンドがいくつかあるものもあります。これrenameはかなり人気のあるPerlのように見えます。しかし、答えは本当にこれを明確にするはずです。
これは、
.pkgを取り除き、次に取り除きます。
for x in $(ls); do echo $x $(echo $x | sed 's/\.pkg//g' | sed 's/-.*//g').pkg; done
-e。例えばsed -e 's/\.pkg//g' -e 's/-.*//g'。
同じフォルダ*.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
Diomidis Spinellisの回答に基づいています。
正規表現は、ファイル名全体に対して1つのグループを作成し、.nzb.queuedの前の部分に対して1つのグループを作成してから、シェル移動コマンドを作成します。文字列が引用されています。これは、sedによって既に行われているため、シェルスクリプトでループを作成することも回避します。
-n同じ方法でオプションを解釈しません。