cp
コマンドのinfo
pageは、オプション--preserve=
で次のことを提供します。
links
対応するソースファイル間のリンクを宛先ファイルに保存します。-L' or
- H 'を使用すると、このオプションcanシンボリックリンクをハードリンクに変換することに注意してください。
[今]得られない例が続きます。とにかく:
質問:cp
を使用してソフトリンクをハードリンクに変換する方法は?そして、[ハードリンクをソフトリンクに変換する]方法もありますか?
二次問題:上記の引用のcanはどこで機能しますか? -L
と-H
の目的を理解し、完全に機能するソフトリンクなどをコピーできますが、これまでのところ、ソフトリンクをハードリンクに変換することはできませんでした。
情報ページの例は、例を理解するのが少し難しい方法を示しています。
$ 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
はシンボリックリンク(ソフトリンク)であり、a
と同じiノードを指していないことに注意してください。
$ 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/
の内容です(最初の列はiノード番号です)。
$ 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 found out として、少なくともDebianシステムでは、ターゲットディレクトリが同じであれば、cp --preserve=links
でシンボリックリンクをハードリンクに変換できます。
バグの可能性に関するレポートをinfo cp
ドキュメントでcoreutilsチーム@ gnu.orgに送信し、次の返信を受け取りました。
ドキュメントはここでは少し簡潔です。主な問題は、-aが-dを意味し、コマンドを期待どおりに機能させるために必要な--no-dereferenceを意味することです。 I.E. --no-ソース内のシンボリックリンクに続くcpを暗黙的に停止するには逆参照が必要です。
ここで示されている詳細を確認して分割するには:
$ 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}
にコマンドライン引数を逆参照するように指示するため、同じiノード番号を持つ2つのファイルを確認し、認識されたハードリンクを保持します。@option{-a}
は@option{--no-dereference}
を意味するため、シンボリックリンクをコピーしますが、後の@option{-H}
は@command{cp}
にコマンドライン引数を逆参照するように指示し、同じiノード番号の2つのファイルを表示します。次に、@option{--preserve=links}
によっても暗示される@option{-a}
オプションは、認識されたハードリンクを保持します。
ハードリンクをシンボリックリンクに変換するのは難しいでしょう。ハードリンクの場合、ファイルシステム上にデータブロックがあり、それを指す2つ以上のファイルエントリがあります。 「ソース」と「宛先」はありません。文字通り、複数の同等の名前を持つ1つのファイルです。 GNU findを使用して、これらを次のように識別できます。
sauer@zipper:~$ find . -type f -links +1 -printf "%i: %p (%n)\n"
609: ./link1 (2)
609: ./link2 (2)
同じiノードを持つすべてのファイルを取得したら、1つを「実際の」ファイルとして選択し、他のすべてのファイルをマスターファイルへのシンボリックリンクに置き換える必要があります。おそらくそれを行う方法はこれを使用することです:
sauer@zipper:~$ find . -type f -links +1 -printf "%i %p\n" | sort -nk1
609 ./link1
609 ./link2
次に、同じ番号の値の1つを選択して、他のすべての値をそれにリンクさせる方法をスクリプトで理解します。たぶん、最初のものがターゲットになり、同じiノードを持つそれ以上のものがそれにシンボリックリンクされます。これは、非常に単純でテストされていないシェルスクリプトの例です。
#!/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)が絶対的でない場合、異なるディレクトリからのリンクが無効なターゲットで作成される可能性があるという潜在的な問題があります。しかし、一般的な考え方は問題ないはずです。