回答:
cd /path/to/your/folder
sed -i 's/foo/bar/g' *
「foo」の出現は「bar」に置き換えられます。
macOSなどのBSDシステムで-i '.bak'
は、マンページごとに「リスクの破損または部分的なコンテンツ」などのバックアップ拡張機能を提供する必要があります。
cd /path/to/your/folder
sed -i '.bak' 's/foo/bar/g' *
sed
、-i
その後に古いファイル名に追加される文字列が必要です。したがって、sed -i .bak 's/foo/bar/g' *.xx
すべての.xx
ファイルを同等の.xx.bak
名前に移動してから.xx
、foo→bar置換を使用してファイルを生成します。
sed -i 's/foo\ with\ spaces/bar/g' *
。私はあなたが久しぶりに気付いたと思います...しかし、このようにして、他の人が同じ問題を見つけられるようにします。
sed -i -e 's/foo/bar/g' $(find /home/user/base/dir)
Kasparの回答に似ていますが、gフラグを使用して、行のすべての出現箇所を置き換えます。
find ./ -type f -exec sed -i 's/string1/string2/g' {} \;
大/小文字を区別しない場合:
find ./ -type f -exec sed -i 's/string1/string2/gI' {} \;
LC_ALL=C find ./ -type f -exec sed -i '' -e 's/proc.priv/priv/g' {} \;
(この投稿とこの投稿を参照)
--include=*.whatever
.git/
。必ずcd
低いレベルに下げてください。
git status
返されますerror: bad index file sha1 signature.... fatal: index file corrupt
。何ができますか?
@kevの答えは適切ですが、直接のディレクトリ内のファイルにのみ影響します。以下の例では、grepを使用してファイルを再帰的に検索しています。それはいつも私のために働きます。
grep -rli 'old-word' * | xargs -i@ sed -i 's/old-word/new-word/g' @
コマンドの内訳
grep -r:-- recursive、各ディレクトリの下のすべてのファイルを再帰的に読み取ります。
grep -l:-- print-with-matchesは、一致する行を出力する代わりに、一致する各ファイルの名前を出力します。
grep -i:-- ignore-case。
xargs:STDINを引数に変換します。この回答に従ってください。
xargsの-i @〜コマンドが含まれている@〜 :引数のプレースホルダ内の特定の位置で使用する〜コマンド〜、@記号は任意の文字列に置き換えることができプレースホルダです。
sed -i:バックアップなしでファイルを編集します。
sed s / regexp / replacement /:regexpに一致する文字列をreplacementで置き換えます。
sed s / regexp / replacement / g:global、最初の一致だけではなく、各一致を置換します。
grep --include={*.php,*.html,*.js} -rnl './' -e "old-word" | xargs -i@ sed -i 's/old-word/new-word/g' @
|
、また、なぜ-i
xargsコマンドで使用しなければならないのかわかりません。私はそれが非推奨であり、-I
代わりに使用する必要があるマニュアルを読みました。そして@
、パターンの開始と終了の区切り文字として使用されていますか?
grep -rli 'old-word' * | xargs -I@ sed -i '' 's/2.0.0/latest/g' @
rli
)と@
記号を壊したとしたらいいでしょう
これは私のために働きました:
find ./ -type f -exec sed -i 's/string1/string2/' {} \;
ハワーバー、これはしませんでした:sed -i 's/string1/string2/g' *
。たぶん、 "foo"はstring1、 "bar"はstring2を意味するものではありませんでした。
find ./ -type f -exec sed -i '' -e 's/string1/string2/' {} \;
これにはすでにリストされているいくつかの標準的な回答があります。一般に、findを使用してファイルを再帰的に一覧表示し、sedまたはperlで操作を実行できます。
ほとんどの場合、rplコマンドの方が覚えやすいでしょう。すべてのファイルに対して再帰的に置換(foo-> bar)します。
rpl -R foo bar .
おそらくそれをインストールする必要があります(apt-get install rpl
または同様のもの)。
ただし、正規表現と逆置換、またはファイルの名前変更と検索と置換を伴うより難しいジョブの場合、私が知っている最も一般的で強力なツールはreprenです。これは、しばらく前に書いた小さなPythonスクリプトです厄介な名前の変更とタスクのリファクタリング。あなたがそれを好むかもしれない理由は:
ファイル内のパスを置き換える(エスケープ文字を避ける)には、次のコマンドを使用できます。
sed -i 's@old_path@new_path@g'
@記号は、後続の文字列ですべての特殊文字を無視する必要があることを意味します。
文字列にスラッシュ(/)が含まれている場合は、区切り文字を「+」に変更できます。
find . -type f -exec sed -i 's+http://example.com+https://example.com+g' {} +
このコマンドは、現在のディレクトリで再帰的に実行されます。
../domain.com
へdomain.com
「foo」の最初の行の出現は「bar」に置き換えられます。また、2行目で確認できます。
grep -rl 'foo' . | xargs sed -i 's/foo/bar/g'
grep 'foo' -r * | awk -F: {'print $1'} | sort -n | uniq -c
grep -rl 'foo' . | xargs sed -i 's/foo/bar/g'
使用できるファイルのリストがある場合
replace "old_string" "new_string" -- file_name1 file_name2 file_name3
使用できるすべてのファイルがある場合
replace "old_string" "new_string" -- *
拡張子付きのファイルのリストがある場合は、使用できます
replace "old_string" "new_string" -- *.extension
replace "old_string" "new_string" -- *.txt
replace
ユーティリティを入手する場所から追加することをお勧めします。この情報がなければ、この答えは不完全です。
「findとsedを使用することもできますが、このperlの小さな行が適切に機能することがわかります。
perl -pi -w -e 's/search/replace/g;' *.php
"(http://www.liamdelahunty.com/tips/linux_search_and_replace_multiple_files.phpから抽出)
私の最良の結果は、perlとgrepを使用して得られます(ファイルに検索式があることを確認するため)
perl -pi -w -e 's/search/replace/g;' $( grep -rl 'search' )
文字列を検索し、search
それreplace
を複数のファイル間で置き換える場合、これは私の戦いでテストされた1行の式です。
grep -RiIl 'search' | xargs sed -i 's/search/replace/g'
grepの簡単な説明:
-R
-再帰検索-i
- 大文字小文字を区別しません-I
-バイナリファイルをスキップします(テキストが必要ですか?)-l
-単純なリストを出力として印刷します。他のコマンドに必要次に、grep出力は、(xargsを介して)sedにパイプされ、実際にテキストを置き換えるために使用されます。-i
フラグは、直接ファイルを変更します。一種の「ドライラン」モードの場合は削除してください。
この質問(と回答)が見つかる前に、自分で解決策を練りました。"replace"、 "several"、および "xml"のさまざまな組み合わせを検索しました。これはそれが私のアプリケーションであるためですが、この特定の組み合わせは見つかりませんでした。
私の問題:複雑なオブジェクトを含むテストケースのデータを含むSpring xmlファイルがありました。Javaソースコードのリファクタリングは多くのクラスを変更し、xmlデータファイルには適用されませんでした。テストケースのデータを保存するために、いくつかのディレクトリに分散されたすべてのxmlファイルのすべてのクラス名を変更する必要がありました。元のxmlファイルのバックアップコピーを保存する間(バージョン管理によってここに保存されるため、これは必須ではありませんでしたが)。
find
+の組み合わせを探していましたsed
ていました。他の状況でも機能しましたが、一度にいくつかの置換を行うことはできませんでした。
それから私はubuntuの応答を見つけました、そしてそれは私が私のコマンドラインを構築するのを助けました:
find -name "*.xml" -exec sed -s --in-place=.bak -e 's/firstWord/newFirstWord/g;s/secondWord/newSecondWord/g;s/thirdWord/newThirdWord/g' {} \;
そして、それは完全に機能しました(まあ、私の場合は6つの異なる置換がありました)。ただし、現在のディレクトリの下にあるすべての* .xmlファイルに触れることに注意してください。そのため、バージョン管理システムに責任がある場合は、最初にフィルタリングして、必要なsed
文字列を実際に持っているものにのみ渡すことをお勧めします。お気に入り:
find -name "*.xml" -exec grep -e "firstWord" -e "secondWord" -e "thirdWord" {} \; -exec sed -s --in-place=.bak -e 's/firstWord/newFirstWord/g;s/secondWord/newSecondWord/g;s/thirdWord/newThirdWord/g' {} \;
findstr /spin /c:"quéquieresbuscar" *.xml
便利です。
MacBook Proでは、以下を使用しました(https://stackoverflow.com/a/19457213/6169225に触発された):
sed -i '' -e 's/<STR_TO_REPLACE>/<REPLACEMENT_STR>/g' *
-i ''
バックアップを取らないようにします。
-e
現代の正規表現。
-e
次のトークンがコマンドであることをsedに伝えます。拡張正規表現の場合は、-E
代わりに使用してください。
ストリームエディターは、-i
スイッチで呼び出されたときに「インプレース」で複数のファイルを変更します。スイッチは、引数として終了するバックアップファイルを取ります。そう
sed -i.bak 's/foo/bar/g' *
このフォルダー内のすべてのファイルでに置き換えfoo
られbar
ますが、サブフォルダーには移動しません。ただし、これ.bak
により、ディレクトリ内のすべてのファイルに対して新しいファイルが生成されます。このディレクトリとそのすべてのサブディレクトリにあるすべてのファイルに対してこれを再帰的に行うには、などのヘルパーfind
がディレクトリツリーをトラバースする必要があります。
find ./ -print0 | xargs -0 sed -i.bak 's/foo/bar/g' *
find
find ./ -name '*.php' -or -name '*.html' -print0
必要に応じて、などの引数をさらに指定することにより、変更するファイルをさらに制限できます。
注:GNU sed
はファイルの終わりを必要とせずsed -i 's/foo/bar/g' *
、同様に機能します。FreeBSD sed
は拡張を要求しますが、間にスペースを許可するのでsed -i .bak s/foo/bar/g *
機能します。
multieditコマンドのスクリプト
multiedit [-n PATTERN] OLDSTRING NEWSTRING
Kasparの回答から、コマンドライン引数を受け入れ、オプションでパターンに一致するファイル名を制限するbashスクリプトを作成しました。$ PATHに保存して実行可能にしてから、上記のコマンドを使用します。
スクリプトは次のとおりです。
#!/bin/bash
_help="\n
Replace OLDSTRING with NEWSTRING recursively starting from current directory\n
multiedit [-n PATTERN] OLDSTRING NEWSTRING\n
[-n PATTERN] option limits to filenames matching PATTERN\n
Note: backslash escape special characters\n
Note: enclose STRINGS with spaces in double quotes\n
Example to limit the edit to python files:\n
multiedit -n \*.py \"OLD STRING\" NEWSTRING\n"
# ensure correct number of arguments, otherwise display help...
if [ $# -lt 2 ] || [ $# -gt 4 ]; then echo -e $_help ; exit ; fi
if [ $1 == "-n" ]; then # if -n option is given:
# replace OLDSTRING with NEWSTRING recursively in files matching PATTERN
find ./ -type f -name "$2" -exec sed -i "s/$3/$4/g" {} \;
else
# replace OLDSTRING with NEWSTRING recursively in all files
find ./ -type f -exec sed -i "s/$1/$2/" {} \;
fi
私の個人的な英語ノードを維持するために、ディレクトリの下のすべてのファイルについて、古い文字列と新しい文字列の複数のペアを再帰的に置き換えるのに役立つユーティリティスクリプトを書きました。
古い文字列と新しい文字列の複数のペアは、ハッシュマップで管理されます。
dirはコマンドラインまたは環境変数を介して設定できます。マップはスクリプトでハードコードされていますが、必要に応じてコードを変更してファイルからロードできます。
新機能のため、bash 4.2が必要です。
en_standardize.sh:
#! /bin/bash
# (need bash 4.2+,)
#
# Standardize phonetic symbol of English.
#
# format:
# en_standardize.sh [<dir>]
#
# params:
# * dir
# target dir, optional,
# if not specified then use environment variable "$node_dir_en",
# if both not provided, then will not execute,
# *
#
paramCount=$#
# figure target dir,
if [ $paramCount -ge 1 ]; then # dir specified
echo -e "dir specified (in command):\n\t$1\n"
targetDir=$1
elif [[ -v node_dir_en ]]; then # environable set,
echo -e "dir specified (in environment vairable):\n\t$node_dir_en\n"
targetDir=$node_dir_en
else # environable not set,
echo "dir not specified, won't execute"
exit
fi
# check whether dir exists,
if [ -d $targetDir ]; then
cd $targetDir
else
echo -e "invalid dir location:\n\t$targetDir\n"
exit
fi
# initial map,
declare -A itemMap
itemMap=( ["ɪ"]="i" ["ː"]=":" ["ɜ"]="ə" ["ɒ"]="ɔ" ["ʊ"]="u" ["ɛ"]="e")
# print item maps,
echo 'maps:'
for key in "${!itemMap[@]}"; do
echo -e "\t$key\t->\t${itemMap[$key]}"
done
echo -e '\n'
# do replace,
for key in "${!itemMap[@]}"; do
grep -rli "$key" * | xargs -i@ sed -i "s/$key/${itemMap[$key]}/g" @
done
echo -e "\nDone."
exit
Pythonソースの一般的なシバンエラーを修正する例を示します。
grep / sedアプローチを試すことができます。以下は、GNU sedで動作し、gitリポジトリを壊さないものです。
$ grep -rli --exclude '*.git*' '#!/usr/bin/python' . | xargs -I {} \
gsed -i '' -e 's/#!\/usr\/bin\/python/#!\/usr\/bin\/env python/' {}
それとも、使用することができますgreptileを :)
$ greptile -x .py -l -i -g '#!/usr/bin/env python' -r '#!/usr/bin/python' .
最初のスクリプトをテストしたところ、2番目のスクリプトも動作するはずです。エスケープ文字には注意してください。ほとんどの場合、greptileを使用する方が簡単だと思います。もちろん、sedを使用して多くの興味深いことを行うことができます。そのためには、xargsを使用して習得することをお勧めします。
私はこれを別の投稿から見つけました(どちらか覚えていません)、最もエレガントではありませんが、シンプルで、初心者のLinuxユーザーとして私に問題を与えていません
for i in *old_str* ; do mv -v "$i" "${i/\old_str/new_str}" ; done
スペースやその他の特殊文字がある場合は、\を使用します
for i in *old_str\ * ; do mv -v "$i" "${i/\old_str\ /new_str}" ; done
サブディレクトリの文字列には**を使用します
for i in *\*old_str\ * ; do mv -v "$i" "${i/\old_str\ /new_str}" ; done
単純なスクリプトファイルを使用することにより、より簡単な方法があります。
# sudo chmod +x /bin/replace_string_files_present_dir
ファイルをgeditまたは任意のエディターで開きます。ここではgeditを使用します。
# sudo gedit /bin/replace_string_files_present_dir
次に、エディターで以下をファイルに貼り付けます
#!/bin/bash
replace "oldstring" "newstring" -- *
replace "oldstring1" "newstring2" -- *
#add as many lines of replace as there are your strings to be replaced for
#example here i have two sets of strings to replace which are oldstring and
#oldstring1 so I use two replace lines.
ファイルを保存し、geditを閉じます、ターミナルを終了するか、単に閉じてから開始し、追加した新しいスクリプトをロードできるようにします。
編集するファイルが複数あるディレクトリに移動します。次に実行します:
#replace_string_files_present_dir
Enterキーを押すと、これらを含むすべてのファイルのoldstringとoldstring1が、それぞれ正しいnewstringとnewstring1に自動的に置き換えられます。
古い文字列を含まないすべてのディレクトリとファイルをスキップします。
これは、文字列の置換が必要なファイルを含むディレクトリが複数ある場合に、入力する面倒な作業をなくすのに役立ちます。あなたがしなければならないすべてはそれらのディレクトリのそれぞれにナビゲートし、次に実行することです:
#replace_string_files_present_dir
あなたがしなければならないのは、上で示したように、すべての置換文字列が含まれているか、追加されていることを確認することだけです。
replace "oldstring" "newstring" -- *
ファイル/ bin / replace_string_files_present_dirの最後。
新しい置換文字列を追加するには、ターミナルで次のように入力して作成したスクリプトを開きます。
sudo gedit /bin/replace_string_files_present_dir
追加する置換文字列の数を心配する必要はありません。古い文字列が見つからない場合、効果はありません。
.gitlab-ci.yml
またはaなどtravis.yml
)にコンパクトバージョンを含めるように求められます。スクリプトを作成して後で実行することで構成されるすべての方向転換は、アンチパターンです。それは、スクリプトの作成をスクリプト化する必要があるためです(そして、私はほとんどの場合面倒になります)
$ replace "From" "To"-`find / path / to / folder -type f`
(replace-MySQLデータベースシステムの文字列置換ユーティリティ)