3

ディレクトリを再帰的に通過するシェルスクリプトを作成しようとしています。各ファイルで、すべての 大文字小文字に変換します。明確にするために、私はファイル名ではなく、ファイル内のテキストを変更しようとしています。

考慮事項:

  1. これは私がもっとアクセスしやすくしようとしている古いFortranプロジェクトです
  2. 新しいファイルを作成するのではなく、変更を加えて古いファイルを上書きします
  3. このディレクトリには、.par .f .txtなど、いくつかの異なるファイル拡張子があります。

これについて行くための最良の方法は何でしょうか?

4

5 に答える 5

6

ファイルを小文字から大文字に変換するには、次を使用できます(標準エディターのex親友):ed

ex -s file <<EOF
%s/[[:upper:]]\+/\L&/g
wq
EOF

または、1行で何かが好きな場合:

ex -s file <<< $'%s/[[:upper:]]\+/\L&/g\nwq'

と組み合わせるとfind、次のことができます。

find . -type f -exec bash -c "ex -s -- \"\$0\" <<< $'%s/[[:upper:]]\+/\L&/g\nwq'" {} \;

この方法は、ファイル名のスペースやおかしな記号に関して100%安全です。補助ファイルは作成、コピー、または移動されません。ファイルは編集されるだけです。

編集。

glenn jackmannの提案を使用して、次のように書くこともできます。

find . -type f -exec bash -c 'printf "%s\n" "%s/[[:upper:]]\+/\L&/g" "wq" | ex -- -s "$0"' {} \;

(長所はそれが厄介な脱出を回避することです;短所はそれがより長いことです)。

于 2012-11-27T22:07:00.203 に答える
2

tr次のように、コマンドを使用して文字の範囲を指定すると、すべての大文字(A〜Z)を小文字(a〜z)に変換できます。

$ tr 'A-Z' 'a-z' <be.fore >af.ter

tr大文字と小文字の変換にこの種の範囲を指定するための特別な構文もあります。

$ tr '[:upper:]' '[:lower:]' <be.fore >af.ter

ユーティリティはtr、指定された入力をコピーして、選択した文字の置換または削除を伴う出力を生成します。trは翻訳または音訳と略されます。パラメータとして2セットの文字を受け取り、最初のセットの文字の出現を他のセットの対応する要素に置き換えます。つまり、文字の変換に使用されます。

tr "set1" "set2" < input.txt > output.txt

正規表現はサポートしていtrませんが、うーん、文字の範囲はサポートしています。

両方の引数が同じ文字数で終わることを確認してください。2番目の引数が短い場合、最初の引数の長さに一致するように最後の文字が繰り返されます。最初の引数が短い場合、2番目の引数は最初の引数の長さに一致するように切り捨てられます。

于 2012-11-27T21:28:09.877 に答える
2

sed -e 's/\(.*\)/\L\1/g' *

または、findからファイルをパイプすることができます

于 2012-11-27T22:47:17.900 に答える
1

@nullrevolutionのソリューションを拡張する:

find /path_to_files -type f -exec sed --in-place -e 's/\(.*\)/\L\1/g' '{}' \;

この1つのライナーは、ベースディレクトリとして/path_to_filesで始まるすべてのサブディレクトリ内のすべてのファイルを検索します。

警告:これにより、* / path_to_file *の下のすべてのディレクトリにあるすべてのファイルの大文字と小文字が変更されるためこのスクリプトを実行する前に、これを実行する必要があることを確認してください。以下を利用して、ファイル拡張子に基づいて検索の範囲を制限できます。

find /path_to_files -type f -name \*.txt -exec sed --in-place -e 's/\(.*\)/\L\1/g' '{}' \;

元のファイルを変更する前に、元のファイルのバックアップを作成することもできます。

find / path_to_files -type f -name * .txt -exec sed --in-place = -orig -e's /(.*)/\L\1/g''{}' \;

これにより、元のファイル名が残りますが、ファイル名に「_orig」が追加された変更されていないコピーが作成されます(つまり、file.txtfile.txt-origになります)。

各作品の説明:

find /path_to_file これにより、ベースディレクトリが指定されたパスに設定されます。

-type fこれにより、ディレクトリ階層でファイルのみが検索されます。

-exec COMMAND '{}' \; これにより、一致したファイルごとに、指定されたコマンドが1回実行されます。は'{}'現在のファイル名に置き換えられます。はコマンドの\;終了を示します。

sed --in-place -e 's/\(.*\)/\L\1/g'--in-place、ファイルをバックアップせずにファイルへのcnagesを作成します。正規表現は、後方参照を使用\1して行全体を参照し、\Lを小文字に変換します。

オプション

(より古風な解決策のために。)

find /path_to_files -type f -exec dd if='{}' of='{}'-lc conv=lcase \;
于 2012-11-27T23:52:29.693 に答える
0

テキストファイルの識別は、Unixライクな環境では少し注意が必要です。あなたはこのようなことをすることができます:

set -e -o noclobber
while read f; do
   tr 'A-Z' 'a-z' <"$f" >"f.$$"
   mv "$f.$$" "$f"
done < <(find "$start_directory" -type f -exec file {} + | cut -d: -f1)

これは、コロンまたは改行が埋め込まれたファイル名では失敗しますが、スペースを含むファイル名では機能するはずです。

于 2012-11-27T21:45:28.493 に答える