複数ファイルの文字列を現在のサブディレクトリ名に変更する

複数ファイルの文字列を現在のサブディレクトリ名に変更する

複数のディレクトリがあり、各ディレクトリには次の行を含むファイルが含まれています。

../a_a_q1.out ../a_a_q2.out ../a_a_q3.out

a_aすべてのサブディレクトリを繰り返し、そのセクションを現在のサブディレクトリ名に変更したいと思います。たとえば、サブディレクトリがと呼ばれる場合は、awesome_directory次の行を読む必要があります。

../awesome_directory_q1.out ../awesome_directory_q2.out ../awesome_directory_q3.out

どうやってこれを達成できますか?

サブディレクトリ名のみを使用したいです。たとえば、awesome_directoryトランザクション全体(//something/server/user/other_stuff/more/awesome_directory)の代わりに()部分のみが必要です。

答え1

Bashの2つの段階には、次の1つの方法があります。

epwd=$(basename `pwd`)
sed -i "s/a_a/$epwd/g" <filename>

この変数には、$epwdsedで使用できるエスケープされたディレクトリ名が含まれています。 sed コマンドは、a_a のすべての発生を作業ディレクトリーに置き換えます。

編集:元の回答の最初の行は、フルパスではなく現在のディレクトリ名のみを含むように編集されました。フルパスを使用するには

epwd=$(pwd|sed 's/\//\\\//g')

答え2

これまで私はこれを思い出しました。

var=("${PWD##*/}")

sed -i "s/a_a/$var/g" filename

答え3

set '%s_q1.out %s_q2.out %s_q3.out\n'
:|for d in several directories
do      cd  -P -- "$d" || ! break
        set "$1" "../${PWD##*/}"
        {   sed -ne'\|\( \.\./a_a_q[123]\.out\)\{3\}|q;s/.//p'
            printf "$@" "$2" "$2";  cut -c2-
        } <<-IN >./infile
        $(paste -d\  - ./infile)
        IN
done

sedこれはPOSIXおよび、、、、、bashシェルなどで機能します。または、シェルを使用すると、ここにある文書が通常のファイルでサポートされる可能性が低いため、共有入力をサポートするために必要な機能に頼ることはできません。このような場合は、上記のシェルのいずれかに切り替える必要があります。zshkshmkshdashyashlseek()

GNUを使用する場合sedだけ。sed -unesed -ne

分析は次のとおりです。

  1. まず、パラメータがあります。フォーマット文字列を繰り返し使用し、次のように設定しますsetprintf$PWD$OLDPWD.

  2. 次に、プロジェクトの繰り返しを開始します。several directories。これが実際のディレクトリでもシンボリックリンクでも、-P物理的な標準パス名を$PWD取得setします$2

  3. 次に起こるのは、heredocリダイレクトの一番下で起こります。シェルが私たちのために保護する安全な一時ファイルにすべてをpaste読み込み、各行の./infile前にスペースを追加します。その後、シェルは一時ファイルをstdinに設定して./infile再割り当てしますが、今回はstdoutとして割り当てます。

  4. sed編集する場合はまれです。一致する行に会う前に、各行の最初の文字を削除してp結果を印刷します。ラインに出会うとq完全に入力されます - 何も印刷されません。

  5. ただし、stdoutに改行が続いてprintf印刷され、中断された部分からstdinを選択します。../${PWD##*/}_q[123].outcutsed(プレイラインの直後)各入力ラインから最初のバイトを削除しながら残りを読み込みます。

したがって、編集されたコンテンツ全体./infileが前の位置に戻ります。

ああ、テストしてみました。

私は変わったseveral directoriesパス名をいくつか変更しました/tmp...

{   seq 7
    echo '../a_a_q1.out ../a_a_q2.out ../a_a_q3.out'
    seq 9 14
    printf %s\\n '' '' ''
}  >/tmp/infile

...一つ書いた/tmp/infile次のようになります。

1
2
サム
4
5
6
7
../a_a_q1.out ../a_a_q2.out ../a_a_q3.out
9
10
11
12
13
14



しかし、上記のコードスニペットを実行した後/tmp...

cat /tmp/infile

1
2
サム
4
5
6
7
../tmp_q1.out ../tmp_q2.out ../tmp_q3.out
9
10
11
12
13
14



答え4

そのa_a部分が一定で、Linuxを実行している場合は、このrenameユーティリティを使用できます。 Debian およびその派生製品では、コマンドは操作を実行しますが、構文が異なる他のユーティリティなので、 にrename変更します。rename.ulrename

ループを使用してディレクトリをナビゲートします。

for d in */; do … done

rename各ディレクトリのファイル名を変更するために呼び出されます。

for d in */; do
  rename /a_a "/${d%/}" "$d"a_a*
done

関連情報