web-dev-qa-db-ja.com

Posixシェルでファイル名の接頭辞を削除する方法

次の例のように、Bashのファイル名プレフィックスを削除するにはどうすればよいですか。

XY TD-11212239.pdf

取得するため

11212239.pdf

つまり、XY TD-を削除しますか?

26
hamid

情報はほとんどありませんが、これをbashで実行していて、プレフィックスを削除する必要があるファイルのリストがある場合、sedを介してリストをパイプすることができます。

例えば:

./generate_your_list_of_files | sed -e 's/^prefix//'

または、ファイルのリストがスペースで区切られている場合:

echo TD-file1 TD-file2.x.yt TD-file3-beep | sed -e 's/\<TD-//g'

最初のものは、行の先頭のプレフィックスに一致し、それを削除します。 2つ目は、単語の先頭で発生した場合にのみTD-(または置換したい他の接頭辞)に一致し、すべての行のすべての一致で置換されます。これはできますでも危険です。たとえば、TD-file\ that\ TD-contains\ space.txtのようなファイルはfile\ that\ contains\ space.txtになります

補足として、lsを使用してファイルのリストを取得しないでください。 それは恐ろしい間違いです 。使用するファイルのリストを取得し、複数の場所で参照する必要がある場合は、配列に配置することをお勧めします。

files=(*)

次に、この配列を操作します。


一般的なリクエスト(下記の単一のコメント)により、ここでは、プレフィックスが削除されるように、XY TD-で始まるディレクトリ内のすべてのファイルの名前を変更する方法を示します(@tripleeeに感謝):

for file in prefix*;
do
    mv "$file" "${file#XY TD-}"
done
29
Shahbaz

あなたは言った[〜#〜] posix [〜#〜] BASH、Kornshell、Ash、Zsh、Dashを含むシェル。さいわい、これらのシェルはすべて、変数値に対してパターンフィルタリングを実行します。

パターンは、Unix/Linuxコマンドラインで*などのファイルを指定するときに使用するものです。

$ ls *.sh  # Lists all files with a `.sh` suffix

これらのPOSIXシェルは、4つの異なるパターンフィルタリングを使用します。

  • ${var#pattern}-パターンに一致する最小の文字列を左側から削除します。
  • ${var##pattern}-パターンに一致する最大の文字列を左側から削除します。
  • ${var%pattern}-パターンに一致する最小の文字列を右側から削除します。
  • ${var%%pattern}-パターンに一致する最大の文字列を右側から削除します。

以下にいくつかの例を示します。

foo="foo-bar-foobar"
echo ${foo#*-}   # echoes 'bar-foobar'  (Removes 'foo-' because that matches '*-')
echo ${foo##*-}  # echoes 'foobar' (Removes 'foo-bar-')
echo ${foo%-*}   # echoes 'foo-bar'
echo ${foo%%-*}  # echoes 'foo'

あなたは本当にあなたが何を望んでいるかを説明しなかったし、どんなコード例も含めなかったので、あなたが望むことをする何かを思いつくのは難しい。ただし、パターンフィルタリングを使用すると、ファイル名を使用して何をしたいかを正確に把握できます。

file_name="XY TD-11212239.pdf"
mv "$file_name" "${file_name#*-}" # Removes everything from up to the first dash
27
David W.

renameツールを使用することもできます

自作でインストール

brew install rename

次に、ディレクトリ内から以下のコマンドを実行して、すべてのファイルから「prefix-」を削除します

rename -d prefix- *

5
Ken Prince

他の回答に示されている部分文字列の抽出に加えて、部分文字列の置換を利用することもできます。ファイルを考えると:

fn="XY TD-11212239.pdf"

次に、以下の部分文字列置換:

fn_new=${fn//*TD-/}

あなたがしたいこともします。

2
David C. Rankin
_$ s='XY TD-11212239.pdf'
$ echo "${s#XY TD-}"
11212239.pdf
_

一括名前変更を実行することが目的の場合:

_while IFS= read -r -d '' filename; do
  mv "$filename" "${filename#XY TD-}"
done < <(find . -type f -name 'XY TD-*' -print0)
_

<()は、POSIX shにはないbash拡張であることに注意してください。これを_find ... | while_形式のパイプラインで置き換えることができます。

同様に、_-print0_は、GNU拡張子はPOSIX検索に存在しません。POSIX検索では、改行を含む名前に対して安全なファイルを見つけるための同等の方法がなく、置換が困難です。

1
Charles Duffy