ハードリンクをインプレースで解除しますか?


13

私はドットファイルをバージョン管理下に置いており、それらを展開するスクリプトはハードリンクを作成します。またetckeeper/etcバージョン管理下に置くためにも使用しています。最近、私はこのような警告を受けました:

warning: hard-linked files could cause problems with bzr

単純なコピー(cp filename.ext filename.ext)は機能しません。

cp: `filename.ext' and `filename.ext' are the same file

ファイルの名前を変更/移動する-ボリューム間を除いて-ハードリンクも壊れません。

だから私の質問は:そのファイルへの他のハードリンクがどこにあるかを実際に知る必要なく、ファイルへのハードリンクを解除する方法はありますか?


2
「rm」コマンドはハードリンクを解除します。
ヨハン

回答:


14
cp -p filename filename.tmp
mv -f filename.tmp filename

スクリプト可能にする:

dir=$(dirname -- "$filename")
tmp=$(TMPDIR=$dir mktemp)
cp -p -- "$filename" "$tmp"
mv -f -- "$tmp" "$filename"

最初にコピーを実行してから所定の位置に移動すると、ファイルがハードリンクから個別のコピーにアトミックに変更されるという利点があります(filename部分的または欠落している時点はありません)。


7

おそらく、ハードリンクを別の独立したファイルに分割したいということです。

mv hardlink tempname && cp tempname hardlink && rm tempname

ハードリンクは、ディレクトリ内のエントリとディスク上のiノードブロック間の接続です。

iノードはファイルメタデータを格納します。小さなファイルの場合、一部のファイルシステムはデータをiノードに格納します。それ以外の場合はデータブロックへのポインター、および非常に大きなファイルの場合は、ディスクアロケーションユニットへのポインターの間接および二重間接リストです。

いずれにしても、ファイル名(lsコマンドが生成するもの)とこのメタデータを格納するiノードブロックの間の接続は、ハードリンクと呼ばれます。

単一のファイルへの複数のハードリンクを持つことは、複数のディレクトリエントリによって参照される同じiノードを意味します(単一のファイルシステム上の)異なるディレクトリにある可能性があります。

rmは、ファイル名エントリをディレクトリから削除します。iノードがどのファイルからも参照されなくなると、そのスペースは解放され、他のファイルで使用できるようになります。


確かに。これは、cpおよびのmv例が意味するものです。したがって、一時ファイルを使用する方法はないと思います。
0xC0000022L 2013年

@ 0xC0000022L、いいえ、iノードには他のiノードへのポインタが含まれていません。データブロックのみ(またはオブジェクトが小さい場合はデータスペースとしても使用できます)。
フォンブランド2013年

4
コピーするときは、権限とその他のデータが保持されていることを確認してください。使用cp -a(少なくともGNU coreutils)。
フォンブランド2013年

@ 0xC0000022L、注意深く見ると、元のファイルには一時的な名前しかなく、新しいファイルは最後のステップでのみ作成されます。
フォンブランド2013年

@vonbrand実際には、使用されているファイルシステムによって異なります。
ヨハン

4

これを〜/ .bashrcファイルの最後に置きます。

delink () { tmpfile="$1$(date)"; cp -a "$1" "$tmpfile"; mv "$tmpfile" "$1"; }

このように実行します

delink filename

3

bashスクリプトでそれを行う最良の方法は、次のようなものです。

if [ -f "$1" ] ; then
dir="$(dirname -- "$1")"
tmpfile="$(mktemp --tmpdir="$dir")"
cp --preserve=all -f -- "$1" "$tmpfile"
mv -f -- "$tmpfile" "$1"
fi

注意点:

  • コピーする前に、ファイルが通常のファイルかどうかを確認してください
  • コピーの準備ができるまで古いファイルをそのままにしておく
  • mktemp存在しないことが保証されているファイルを生成するために使用します
  • 使用-f上書き強制すると--preserve=all、元のファイルに可能な限り類似したなどのメタデータを維持するために
  • --"を使用して、スペースを含むパスを引用します。-

一時ファイルを作成せずに置換を行うことは、現在の(3.16)Linuxシステムコールでは不可能です。アトミックにファイルを上書きすることができます(つまり、古いファイルを削除して、単一の操作として新しいファイルで置き換える)ことができます。ファイルシステムに名前のないファイル(つまり、関数のO_TMPFILEフラグを使用して作成された一時ファイル)でこれを行うことはできません。これはopenrename関数が入力としてファイル名を必要とするためです(rename入力としてファイル記述子をとるバージョンはありません-詳細はこちらをご覧ください)


1
dirnameとのmktemp呼び出しで名前を引用できなかったことに注意してください。あなたのために修正しました...
derobert、2014

@derobertああありがとうございますが、二重引用符がネストされているため、これは機能しません...別の修正が必要です!
ちょっと

3
- $( ... )スタイルのコマンド置換により機能します。その理由の1つは、` ... `スタイルよりも優れています。
derobert 2014

@derobertいいね、知らなかった。また、インラインコードタグ内で `をどのように使用できますか?
pqnet 2014

バックスラッシュでエスケープできます。だから`あなたを入れてもらうために:(`\``もちろん、私はそれをあなたがタイプしたものを示すためにそれを取得するためにダブルエスケープしました)
derobert 2014

-1

あなたが探しているコマンドは unlink


おそらく、私の質問は明確ではありませんでしたが、による「インプレース」としての例cpmv私はその後に存在するファイルを希望していることを明確にするためのもの。
0xC0000022L 2013年

ああ、はっきりとはわかりませんでした。それなら、ヨハンの答えで行かなければならない。
ジェニーD

1
コマンド "unlink"は、単にファイルを削除します(unlink()システムコールが行うこと)。
ラウル・サリナス- Monteagudo

-1

あなたがこのファイルへのハードリンクであるすべてのファイル名を探しているなら、あなたは使うことができます:

find -samefile myknowhardlinkfile

ls -il myknowhardlinkfile同じiノード(3番目のフィールド)にハードリンクされたファイル名の数も表示されます。

101612442 -rw-rw-r--. 2 me me 0 Aug  5 07:07 myknowhardlinkfile

役に立つかもしれませんが、これは実際には質問の答えにはなりません。
Flimm 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.