4

ディレクトリ名を変更しました。このディレクトリには何千ものファイルがあります。一部のプロジェクトはこのファイルを使用し、プロジェクトにはシンボリック リンクがあります。

  1. アドレスにフォルダ名が含まれているすべてのシンボリックリンクを見つける方法は?
  2. このすべてのシンボリックリンクを自動モードで別のパスに変更するには?

削除と新規作成を伴うbashスクリプトのみの場合-私はそれを行いますが、もっと簡単な方法を知っているでしょうか?

4

1 に答える 1

16
  1. 少し複雑ですが、シンボリックリンクが相対かどうかをテストし、パス名を取り除くためのチェックでfind実行できます(この回答から1:1をコピー)。(シンボリックリンクのターゲットがもう存在しないため 、最も便利なメソッド( など)は使用できないことに注意して ください。)古いパスが次の場合:readlinksed..
    readlink -f
    /var/lib/old/path

    oldpath='/var/lib/old/path';
    find / -type l -execdir bash -c 'p="$(readlink "{}")"; if [ "${p:0:1}" != "/" ]; then p="$(echo "$(pwd)/$p" | sed -e "s|/\./|/|g" -e ":a" -e "s|/[^/]*/\.\./|/|" -e "t a")"; fi; if [ "${p:0:'${#oldpath}'}" == "'"$oldpath"'" ]; then ...; fi;' \;
    
  2. ...上記の をln -sf(-f既存のリンクを上書きするために) に置き換えます。新しいパスが次のとおり
    であると仮定します。/usr/local/my/awesome/new/path

    oldpath='/var/lib/old/path';
    newpath='/usr/local/my/awesome/new/path';
    find / -type l -execdir bash -c 'p="$(readlink "{}")"; if [ "${p:0:1}" != "/" ]; then p="$(echo "$(pwd)/$p" | sed -e "s|/\./|/|g" -e ":a" -e "s|/[^/]*/\.\./|/|" -e "t a")"; fi; if [ "${p:0:'${#oldpath}'}" == "'"$oldpath"'" ]; then ln -sf "'"$newpath"'${p:'${#oldpath}'}" "{}"; fi;' \;
    

oldpathandnewpathは絶対パスでなければならないことに注意してください。
また、これによりすべての相対シンボリックリンクが絶対シンボリックリンクに変換されることに注意してください。
それらを相対的に保つことは可能ですが、多くの努力が必要です。

分解する

その1行のインフェルノが実際に何を意味するのか気になる人のために:

  • find- クールな実行ファイル
  • /- 検索する場所、この場合はシステム ルート
  • -type l- シンボリックリンクに一致
  • -execdir- 一致ごとに、一致したファイルのディレクトリで次のコマンドを実行します。
    • bash-まあ、バッシュ
    • -c- 次の文字列を実行します (先頭と末尾'は削除されます)。
      • p="$(readlink "{}")";- 最も内側から開始:
        • "- 文字列を開始して、展開が発生しないことを確認します
        • {}- 一致したファイルの名前のプレースホルダー ( の機能-execdir)
        • "- 文字列を終了します
        • readlink ...- シンボリックリンクが指している場所を見つける
        • p="$(...)"- 結果を格納します$p
      • if [ "${p:0:1}" != "/" ]; then- の最初の文字$p/(つまり、シンボリック リンクが絶対) の場合、...
      • p="$(echo "$(pwd)/$p" | sed -e "s|/\./|/|g" -e ":a" -e "s|/[^/]*/\.\./|/|" -e "t a")";- パスを絶対パスに変換します。
        • $(pwd)- 現在のディレクトリ ( を使用しているため、一致したファイルがある場所-execdir)
        • /$p- 作業ディレクトリのパスにスラッシュとシンボリックリンクのターゲットを追加します
        • echo "$(pwd)/$p" |- 上記を次のコマンドにパイプします
        • sed ...- すべての を解決します。ここ..を参照してください
        • p="$(...)"結果を に保存し$pます。
      • fi;- 終わりif
      • if [ "${p:0:'${#oldpath}'}" == "'"$oldpath"'" ];- で$p始まる場合$oldpath
        • ${p:0:'${#oldpath}'}- の部分文字列、$p位置 から始まり、0長さ$oldpath:
          • ${#oldpath}- 変数の長さ$oldpath
          • '...'- 引用符で囲まれた'文字列の中にいるため必須
      • then- それから...
      • ln -sf- 引数を使用して、シンボリックにリンクし、既存のファイルをオーバーライドします。
        • "'"$newpath"'${p:'${#oldpath}'}"$oldpath- の部分を$p次のように置き換えます(実際には longからできるだけ$newpath多くの文字を削除し、その前に追加します): $p$oldpath$newpath
          • "- 文字列を開始します
          • '- '-string 引数を終了しますbash -c
          • "- 以下を含む"-string を追加します (変数展開が行われる場所)。
          • $newpath- の値$newpath
          • "- "-string 引数を終了しますbash -c
          • '-'以下を含む -string を追加します。
          • ${p:- の部分文字列、p次で始まる:
          • '- 議論を終わらせるbash -c
          • ${#oldpath}- の長さ$oldpathをそれに追加
          • '- 別の'文字列を追加
          • }- 部分文字列の終了
          • "- エンドストリング
        • "{}"- パスが同じままのリンク ファイル
      • fi;- 終わりif
  • \;- 区切り文字-execdir
于 2015-06-24T10:25:09.380 に答える