
コマンド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;
:空のファイルを作成する簡単な方法です。は何もしない bash 組み込みと同じです。を参照echo "" > a
してください。:
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
ドキュメントにある可能性のあるバグに関するレポートをcoreutils team@gnu.orgに送信し、info cp
回答しました。
ここにある文書は少し簡潔です。主な問題は、-aが-dを意味し、コマンドが期待どおりに機能するようにするために必要な--no-dereferenceを意味することです。 cp がソースのシンボリックリンクに従うのを暗黙的に停止するには、IE --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}
指示されたので、同じinode番号を持つ2つのファイルを見て、認識されたハードリンクを維持します。@command{cp}
- これはシンボリックリンクをコピーする
@option{-a}
こと@option{--no-dereference}
を意味しますが、後者はコマンドライン引数を逆参照することを意味する@option{-H}
ので@command{cp}
、同じinode番号を持つ2つのファイルが表示されます。これにより、この@option{--preserve=links}
オプションは@option{-a}
認識されたハードリンクが保存されることを意味します。
答え3
ハードリンクをシンボリックリンクに変換することは困難です。ハードリンクの場合、ファイルシステムには2つ以上のファイルエントリがそれを指すデータブロックがあります。 「ソース」と「対象」はありません。実際には同じ名前の複数のファイルです。 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つを選択して、他のすべての値を連結する方法をスクリプトで確認します。おそらく、最初のノードがターゲットになり、同じノードを持つ他のノードがそのノードにシンボリックリンクされる可能性があります。これは非常にシンプルでテストされていないシェルスクリプトの例です。
#!/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)が絶対パスではない場合、誤った宛先として他のディレクトリへのリンクが生成される可能性があるため、潜在的な問題があります。しかし、一般的なアイデアは大丈夫でしょう。