1

ディレクトリ パス内の文字列を別の文字列に置き換える方法を見つけようとしてエラーが発生しました

sed: Error tryning to read from {directory_path}: It's a directory 

シェルスクリプト

#!/bin/sh

R2K_SOURCE="source/"
R2K_PROCESSED="processed/"
R2K_TEMP_DIR=""

echo " Procesando archivos desde $R2K_SOURCE "

for file in $(find $R2K_SOURCE )
do
        if [ -d $file ]
        then
                R2K_TEMP_DIR=$( sed 's/"$R2K_SOURCE"/"$R2K_PROCESSED"/g' $file )
                echo "directorio $R2K_TEMP_DIR"
        else
#               some code executes
                :
        fi
done

# find $R2K_PROCCESED -type f -size -200c -delete

エラーがこの行にあることを理解しています

R2K_TEMP_DIR=$( sed 's/"$R2K_SOURCE"/"$R2K_PROCESSED"/g' $file )

しかし、$file変数をディレクトリオブジェクトとしてではなく文字列として扱うことをshに伝える方法がわかりません。

4

2 に答える 2

8

パス名の一部を置き換えたくない場合は、パス名をエコーし​​て、パイプ経由で sed に渡すことができます。また、sed コマンドを一重引用符ではなく二重引用符で囲み、「s」コマンドのセパレーターを次のように変更して、グロビングを有効にする必要があります。

R2K_TEMP_DIR=$(echo "$file" | sed "s:$R2K_SOURCE:$R2K_PROCESSED:g")

これで、's' コマンド内でスラッシュを使用して操作できるようになります。

アップデート:

さらに良いのは、無駄なエコーを削除して、代わりに「here is string」を使用することです。

R2K_TEMP_DIR=$(sed "s:$R2K_SOURCE:$R2K_PROCESSED:g" <<< "$file")
于 2013-04-25T19:07:59.037 に答える
4

まず、使用しないでください:

for item in $(find ...)

コマンドラインをオーバーロードする可能性があるためです。また、 for ループは のプロセスが$(...)終了するまで開始できません。その代わり:

find ... | while read item

ファンキーなファイル名にも注意する必要があります。ループは、forスペースを含むすべてのファイルで咳をします。ファイルfind | whileの名前にスペースが 1 つだけ含まれていて、スペースが 2 つ含まれていない限り、これは機能します。より良い:

find ... -print0 | while read -d '' -r item

これにより、ファイル名の間にヌルが挿入readされ、それらのヌルで中断されます。このようにして、スペース、タブ、改行、または問題を引き起こす可能性のあるその他のものを含むファイルを問題なく読み取ることができます。

あなたのsed行は次​​のとおりです。

R2K_TEMP_DIR=$( sed 's/"$R2K_SOURCE"/"$R2K_PROCESSED"/g' $file )

$fileこれがしようとしているのは、ディレクトリであるあなたの編集です。あなたがしたいことは、ディレクトリ名自体を変更することです。したがって、名前をsedパイプとしてエコーする必要があります。

R2K_TEMP_DIR=$(echo $file | sed 's/"$R2K_SOURCE"/"$R2K_PROCESSED"/g')

ただし、環境変数パラメータを使用して環境変数をフィルタリングする方がよい場合があります。

基本的に、というディレクトリがあり、source/探しているすべてのファイルはそのディレクトリの下にあります。あなたは単に変更したい:

 source/foo/bar

 processed/foo/bar

この ${file#source/} のようなことができます。は#、これが左側のフィルターであり、#. マンページをチェックして、Parameter Expansionbashの下を見てください。

これは、次のようなことができます。

#!/bin/sh

R2K_SOURCE="source/"
R2K_PROCESSED="processed/"
R2K_TEMP_DIR=""

echo " Procesando archivos desde $R2K_SOURCE "

find $R2K_SOURCE -print0 | while read -d '' -r file
do
    if [ -d $file ]
    then
        R2K_TEMP_DIR="processed/${file#source/}"
        echo "directorio $R2K_TEMP_DIR"
    else
#       some code executes
        :
    fi
done

R2K_TEMP_DIR="processed/${file#source/}"source/の先頭から を削除し、その場所に$file追加するだけです。processed/

さらに良いことに、それははるかに効率的です。元のスクリプトでは、$(..)別のシェル プロセスを作成して実行echoし、別のプロセスにパイプして実行しますsed。( loentarのソリューションを使用すると仮定します)。実行中のサブプロセスはもうありません。ディレクトリ名の変更全体は内部的なものです。

ちなみに、これもうまくいくはずです:

R2K_TEMP_DIR="$R2K_PROCESSED/${file#$R2K_SOURCE}"

私はそれをテストしませんでした。

于 2013-04-25T19:54:33.530 に答える