grepとforを使用してファイルの名前を変更する

grepとforを使用してファイルの名前を変更する

.txt、.data、.conf拡張子を持つファイル名を「.xml」に変更したいと思います。

Hello.txt -> Hello.xml

これを行うには、ファイルに次の行も含める必要があります。<?xml version="1.0" encoding="UTF-8"?>

これが私が持っているものです:

for file in *
do
if [ $(grep -Rc '<?xml version="1.0" encoding="UTF-8"?>' --include ".txt" --include ".data" --include "*.conf") = true ]
then
rename extension to: .xml
fi
done

どんなアイデアがありますか?

答え1

もしあなたなら必要grepそれでは、forこのようなことが起こりますか?

grep -RlZ '<?xml version="1.0" encoding="UTF-8"?>' --include "*.txt" --include "*.data" --include "*.conf" | 
  xargs -0 sh -c 'for f; do echo mv -- "$f" "${f%.*}.xml"; done' sh

echo正しいことをしていると確信している場合は削除してください)。

  • grep -RlZ一致する項目が見つかったファイル名の空の区切りリストを出力します。

  • xargs -0この空で区切られたリストを次に渡します。sh -c

  • for f位置引数でファイル名を繰り返します。

whileまたは(代わりに利用可能な場合for)、xargsシェルスクリプトレットをスキップして追加することもできます。

grep -RlZ '<?xml version="1.0" encoding="UTF-8"?>' --include "*.txt" --include "*.data" --include "*.conf" | 
  while IFS= read -r -d '' f; do echo mv -- "$f" "${f%.*}.xml"; done

答え2

find . -type f \( -name "*.txt" -o -name "*.data" -o -name "*.conf" \) -exec sh -c '
    for file in "$@"; do
        if grep -qF "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" "$file"; then
            mv -- "$file" "${file%.*}.xml"
        fi
    done
' findshell {} +

findこの場合はより適していると思います。.txt.data拡張子を持つ通常のファイルを繰り返し検索し、ユーザーが.conf提供した文字列が各ファイルに存在することを確認します。その場合、.xml拡張子は via command に変更されますmv

コードが期待どおりに機能するかどうかわからない場合は、echoコードを前に追加してコードが何をしているのかmvを確認できます。

また、このスクリプトはPOSIX以外のユーティリティに依存しないことにも言及したいと思います。

答え3

次のことを試すことができます。

for file in *.{txt,conf}; do 
  [[ $(grep "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" "$file") ]] && \
  mv "$file" "${file%.*}.xml" || echo "$file" " does not match"
done

答え4

使用bash:

shopt -s globstar dotglob nullglob extglob

string='<?xml version="1.0" encoding="UTF-8"?>'

for pathname in ./**/*.@(txt|data|conf); do
    if [[ -f $pathname ]] && grep -q -F "$string" "$pathname"; then
        mv -i "$pathname" "${pathname%.*}.xml"
    fi
done

まず、通常デフォルトで設定されていないいくつかのシェルオプションを設定しますbash

  • globstar繰り返し一致するサブディレクトリに対してワイルドカードモードを有効にします**
  • dotglobワイルドカードパターンを隠された名前と一致させます。
  • nullglob拡張されていないまま残る代わりに、一致しないパターンを完全に消えます。これにより、一致するものがないと後でループが実行されなくなります。
  • extglob@(txt|data|conf)括弧で囲まれた文字列の1つと一致するなど、拡張ワイルドカードパターンを有効にします。

次に候補名を繰り返し、与えられた文字列に対して各名前をテストします。文字列が見つかったら、最後のドット文字の後のファイル名のサフィックスをxml

関連情報