コマンドcp
のページには、次のinfo
オプションが表示されます。--preserve=
links
対応するソースファイル間のリンクを宛先ファイルに保存します。-H'と組み合わせると-L' or
、このオプションはできるシンボリックリンクをハードリンクに変換する。
続いて、私には(今は)分からない例が続きます。とにかく:
質問: ソフトリンクをハードリンクに変換するにはどうすればいいですかcp
? また、ハードリンクをソフトリンクに変換する方法もありますか?
二次問題: どこでやるできる上記の引用にある は関係ありますか? と の目的は理解していますし-L
、-H
完全に機能するソフトリンクなどをコピーすることはできますが、これまでのところソフトリンクをハードリンクに変換することはできませんでした。
答え1
情報ページの例では、少しわかりにくい例ではありますが、どのように行われるかが示されています。
$ mkdir c; : > a; ln -s a b; cp -aH a b c; ls -i1 c
74161745 a
74161745 b
これをコンポーネント コマンドに分解してみましょう。
mkdir c;
: ディレクトリを作成しますc/
: > a;
: 空のファイルを簡単に作成する方法です。 と同じですecho "" > a
。:
は何もしない bash 組み込みコマンドですhelp :
。を参照してください。ln -s a b
a
: と呼ばれるソフトリンクを作成しますb
。この時点で、現在のディレクトリの内容は次のとおりです。$ ls -l | cc2ter total 4 -rw-r--r-- 1 terdon terdon 0 Oct 9 02:50 a lrwxrwxrwx 1 terdon terdon 1 Oct 9 02:50 b -> a drwxr-xr-x 2 terdon terdon 4096 Oct 9 02:50 c
b
はシンボリック リンク (ソフト リンク) なので、次のものと同じ inode を指していないことに注意してくださいa
。$ ls -i1c a b 16647344 a 16647362 b
cp -aH a b c;
: ファイルをa
およびb
ディレクトリにコピーしますc
。ここで変換が行われ、渡されるオプションは次のcp
とおりです。-a, --archive same as -dR --preserve=all -d same as --no-dereference --preserve=links -H follow command-line symbolic links in SOURCE
は
-H
、次の理由で必要です ( よりinfo cp
):シンボリック リンクからコピーする場合、`cp' は通常、再帰的にコピーしない場合にのみリンクをたどります。
-a
は再帰コピー (-R
)を有効にするため、-H
シンボリック リンクをたどるには が必要です。-H
は、再帰にもかかわらずリンクがたどられ、ターゲット ディレクトリにハード リンクが作成されることを意味します。 これらは、最後の手順後の の内容ですc/
(最初の列は inode 番号です)。$ ls -li c total 0 17044704 -rw-r--r-- 2 terdon terdon 0 Oct 9 02:50 a 17044704 -rw-r--r-- 2 terdon terdon 0 Oct 9 02:50 b
さて、それがどのように機能するかについては、私が試してみた限りでは、またはcp --preserve=links
と組み合わせて、シンボリックリンクをハードリンクに変換します。-L
-H
リンクとターゲットの両方がコピーされ、同じディレクトリ。
実際、OPが言うように見つけた少なくとも Debian システムでは、cp --preserve=links
ターゲット ディレクトリが同じであれば、シンボリック リンクをハード リンクに変換するにはこれで十分です。
答え2
info cp
ドキュメント内の coreutils チーム @gnu.org にバグの可能性に関するレポートを送信したところ、次のような返信が返ってきました。
このドキュメントは少々簡潔です。主な問題は、-a が -d を暗示し、それが --no-dereference を暗示することであり、これはコマンドを期待どおりに動作させるのに必要です。つまり、cp がソース内のシンボリックリンクを暗黙的にたどるのを止めるには --no-dereference が必要です。
ここで説明されている詳細を検証して分割するには、次の手順を実行します。
$ mkdir links; : > a; ln -s a b;
ここで、-d が後続の -H をオーバーライドしていることがわかります。したがって、そもそもシンボリックリンクを参照解除しません。
$ rm links/*; cp -H -d a b links $ l links/ lrwxrwxrwx. 1 padraig 1 Oct 10 09:37 b ▪▶ a -rw-rw-r--. 1 padraig 0 Oct 10 09:37 a
ここで、-H が最後に来るため尊重され、ソースでシンボリック リンクがたどられ、結果として宛先にハード リンクが作成されることがわかります。
$ rm links/* $ rm links/*; cp -d -H a b links $ l links -rw-rw-r--. 2 padraig 0 Oct 10 09:37 b -rw-rw-r--. 2 padraig 0 Oct 10 09:37 a
ドキュメントを次のようにもう少し明確にします。
diff --git a/doc/coreutils.texi b/doc/coreutils.texi index b273627..aeed4ca 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -8257,9 +8257,11 @@ $ mkdir c; : > a; ln -s a b; cp -aH a b c; ls -i1 c @noindent
入力に注意してください:
@file{b}
は通常のファイルへのシンボリックリンクです@file{a}
が、宛先ディレクトリ 内のファイルは@file{c/}
ハードリンクされています。
- は
@option{-a}
を意味し@option{--preserve=links}
、 はコマンドライン引数を参照解除するように@option{-H}
指示しているので@command{cp}
、 は同じ inode 番号を持つ 2 つのファイルを認識し、認識されたハード リンクを保持します。- はシンボリックリンクをコピーすること
@option{-a}
を意味します@option{--no-dereference}
が、後者はコマンドライン引数を逆参照するように@option{-H}
指示し、同じ inode 番号を持つ 2 つのファイルを確認します。次に、 によっても暗示されるオプションは、認識されたハードリンクを保持します。@command{cp}
@option{--preserve=links}
@option{-a}
答え3
ハードリンクをシンボリックリンクに変換するのは難しいでしょう。ハードリンクの場合、ファイルシステム上に 2 つ以上のファイルエントリがポイントしているデータブロックがあります。「ソース」と「宛先」はありません。文字どおり、複数の同等の名前を持つ 1 つのファイルです。GNU find を使用して、次のように識別できます。
sauer@zipper:~$ find . -type f -links +1 -printf "%i: %p (%n)\n"
609: ./link1 (2)
609: ./link2 (2)
同じ inode を持つすべてのファイルを取得したら、そのうちの 1 つを「実際の」ファイルとして選択し、他のすべてのファイルをマスター ファイルへのシンボリック リンクに置き換える必要があります。おそらく、これを行うには、次の方法を使用します。
sauer@zipper:~$ find . -type f -links +1 -printf "%i %p\n" | sort -nk1
609 ./link1
609 ./link2
そして、スクリプトで同じ番号を持つ値の 1 つを選択して、他のすべての値をそれにリンクさせる方法を考えます。おそらく最初の値がターゲットになり、同じ inode を持つ他の値はそれにシンボリックリンクされます。これは、非常にシンプルでテストされていないシェル スクリプトの例です。
#!/bin/sh
prev=""
target=""
find /tmp -type f -links +1 -printf "%i %p\n" | sort -nk1 \
| while read inode file
do
if [[ $inode != $prev ]]
then
target="$file"
prev=$inode
else
ln -sf "$target" "$file"
fi
done
find のパス (この例では /tmp) が絶対パスでない場合、異なるディレクトリからのリンクが無効なターゲットで作成される可能性があるという潜在的な問題があります。ただし、基本的な考え方は問題ないはずです。