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 -n
mvコマンドの生成をサポートするかどうかはわかりません。(注: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
。
これはかなり小さな変更なので、その機能を含めるとよいでしょう。
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パターンルールが適用されます。これらのパターンはPCRE(Perl互換の正規表現)ではありません。どちらsed -r
かを使用するかsed -E
、プラットフォームに応じて、拡張正規表現構文をsedにすることができます。
man re_format
sedの基本および拡張正規表現パターンの詳細については、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
同じ方法でオプションを解釈しません。