一連のパッケージの名前を変更してバージョン番号を削除するにはどうすればよいですか?私は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
スペースを含むファイル名には引用符が必要です。
すべてのファイルが同じディレクトリにある場合、シーケンス
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では、正規表現のグループ化シーケンスは、単一のブラケット\(
および\)
ではなく、バックスラッシュ(
および)
が前に付いたブラケットです。 。
私はこのようなことをします:
for file in *.pkg ; do
mv $file $(echo $file | rev | cut -f2- -d- | rev).pkg
done
すべてのファイルが現在のディレクトリにあると仮定します。そうでない場合は、上記のJavierのアドバイスに従ってfindを使用してみてください。
[〜#〜] edit [〜#〜]:また、このバージョンは上記の他のような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.]*
は受け入れられた回答から除外しました。これは正規表現ではなく、globパターンです。したがって、「ダッシュの後にゼロ個以上の数字またはドットが続く」という意味ではありません。代わりに、「ダッシュ、それに数字またはドット、それに続くもの」を意味します。 「何でも」は可能な限り最短の一致であり、最長ではありません。 (Bashは##
および%%
を提供して、最短ではなく最長のプレフィックスまたはサフィックスをトリミングします。)
sed
が* nixで利用可能であると想定できますが、mvコマンドを生成するためにsed -n
をサポートするかどうかはわかりません。 (注:のみGNU sed
はこれを行います。)
それでも、bash builtinsと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
の初期バージョンを使用できません。
それはかなり小さな変更なので、その機能を含めることは素晴らしいことです:
Bashにはこの組み込み機能がないため、ユーティリティ関数abspath
(または絶対パス)が必要です。
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 Compatible Regular Expressions)ではありません。プラットフォームに応じてsed -r
またはsed -E
を使用して、拡張正規表現構文をsedできます。
Sedの基本および拡張正規表現パターンの完全な説明については、POSIX準拠のman re_format
を参照してください。
これには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
正規表現を理解することは練習問題として残されます(スペースを含むファイル名を扱う場合と同様)
名前の変更は、この種のことを行うためのはるかに簡単なツールであることがわかりました。 OSXのHomebrewで見つけました
あなたの例では、私はそうします:
rename 's/\d*?\.\d*?\.\d*?//' *.pkg
「s」は代替を意味します。フォームはs/searchPattern/replacement/files_to_applyです。これには正規表現を使用する必要がありますが、少し勉強する必要がありますが、努力する価値があります。
同じフォルダに複数の*.txt
ファイルの名前を.sql
に変更しました。以下は私のために働いた:
for i in \`ls *.txt | awk -F "." '{print $1}'\` ;do mv $i.txt $i.sql; done
これは、
.pkgを削除し、次に削除します-..
for x in $(ls); do echo $x $(echo $x | sed 's/\.pkg//g' | sed 's/-.*//g').pkg; 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によって既に行われているため、シェルスクリプトでループを作成することも避けます。