別のサブディレクトリにある一部のファイルの行を変更したいと思います。ファイルの拡張子は常に存在し、.dct
作業ディレクトリの他のサブディレクトリにあるサブディレクトリには常に存在しますmod
(ただし、サブディレクトリが多いためmod
使用しますfind
)。しかし、私が変更したい文字列はディレクトリ(Windows - > Unix)です。
で関連ファイルを入手できますfind . -type f -path '*/mod/*.dct
。で関連行を変更してみましたsed -e 's/cd c:\\project\\data\\/cd \/project\/data\//' $(basename {}) > $(basename {}).mod
。
私は犯人になる脱出されたバックスラッシュで範囲を絞りました。これは働きます:
find . -type -f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/c://' $(basename {}) > $(basename {}).mod"
以下は行われません。
find . -type -f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/c:\\//' $(basename {}) > $(basename {}).mod"
これはエラーです。
sed: -e expression #1, char 7: unterminated `s' command
このchar 7
部分は脱出に問題があると思います。そんなようですが、どう修正できるかわかりません。これを説明するために、以下が機能します。
find . -type -f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/c:\\//' $(basename {}) > $(basename {}).mod"
したがって、「何でも置換」sed -e 's/c:\\///'
にエスケープされ、「何に置き換え」の代わりに「...に置き換え」(そしてエラーが発生した)にエスケープされたように見えます。c:\/
sed -e 's/c:\\//'
c:\/
c:\
注:代わりに-execdir
and を使用するのは少し過剰かもしれませんが、どこかでこれが良い形式であることを読んでいます。basename
-exec
答え1
質問の鍵は、fromを呼び出してバックスラッシュ(例\
:)をスラッシュ(例:)に置き換える方法です。/
これを行うには、文字列が呼び出しによって1回、呼び出しによって2回、2回処理されるため、バックスラッシュを2回エスケープする必要があります。これにより、次の情報が提供されます。sed
find
find
sed
find . -type f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/cd c:\\\\project\\\\data\\\\/cd \/project\/data\//' $(basename {}) > $(basename {}).mod" \;
以下は、より詳細な説明です。
まず、問題の少し簡単な例を設定しましょう。
# Create a target directory
mkdir -p /tmp/dir1/mod/dir2
# Create a text file containing a backslash
echo '\' > /tmp/dir1/mod/dir2/file.dct
それではバックスラッシュを使っfind
てsed
それをスラッシュに変えましょう。
find /tmp/dir1 -type f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/\\/\//' $(basename {})" \;
これにより、次のエラーが発生します。
sed: -e expression #1, char 7: unterminated `s' command
sed
これは、実行されるコマンドが次のようになるためです。
sed -e 's/\/\//' ./file.dct
次のコマンドを直接実行して、同じエラーが発生するかどうかを確認できます。例:
sed -e 's/\/\//' /tmp/dir1/mod/dir2/file.dct
次のコマンドを実行して確認することもできますecho
。find
find /tmp/dir1 -type f -path '*/mod/*.dct' -execdir echo "sed -e 's/\\/\//' $(basename {})" \;
コマンドを変更するには、バックスラッシュを2回エスケープします。
find . -type f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/\\\\/\//' $(basename {})" \;
これにより、目的の結果が生成されます。
/