koşarım
ln /a/A /b/B
a
A dosyasının işaret ettiği klasörü görmek isterim ls
.
koşarım
ln /a/A /b/B
a
A dosyasının işaret ettiği klasörü görmek isterim ls
.
Yanıtlar:
Dosyanızın inode numarasını bulabilirsiniz.
ls -i
ve
ls -l
referans sayısını gösterir (belirli bir inode'a verilen hardlinks sayısı)
inode numarasını bulduktan sonra, aynı inode'a sahip tüm dosyaları arayabilirsiniz:
find . -inum NUM
NUM inode için dosya isimleri geçerli dir (.) 'de
Sorunuza gerçekten iyi tanımlanmış bir cevap yok. Sembolik bağlantılardan farklı olarak, hardlinks "orijinal dosyadan" ayırt edilemez.
Dizin girişleri bir dosya adından ve bir inode için bir işaretçiden oluşur. Sırayla inode, dosya meta verilerini ve (işaretçilere gerçek dosya içeriğini gösterir). Bir sabit link oluşturmak, aynı inode için başka bir dosya adı + referansı oluşturur. Bu referanslar tek yönlüdür (tipik dosya sistemlerinde, en azından) - inode yalnızca referans sayısını tutar. Hangisinin "orijinal" dosya adının olduğunu bulmanın hiçbir içsel yolu yoktur.
Bu arada, sistem bir çağrının "silmek" için çağrılmasının nedeni budur unlink
. Sadece bir hardlink kaldırır. İnode eklenmiş bir veri sadece inode referans sayısı 0'a düşerse silinir.
Belirli bir inode için diğer referansları bulmanın tek yolu, hangi dosyaların söz konusu inode'a başvurduğunu kontrol eden dosya sistemi üzerinde kapsamlı bir şekilde arama yapmaktır. Bu kontrolü yapmak için kabuktan 'test A -ef B' kullanabilirsiniz.
UNIX'in sabit bağlantıları ve sembolik bağlantıları vardır ( sırasıyla "ln"
ve ile yapılır "ln -s"
). Sembolik bağlantılar, basit bir şekilde başka bir dosyanın gerçek yolunu içeren ve dosya sistemlerini geçebilen bir dosyadır.
Sabit bağlantılar, UNIX'in ilk günlerinden beri (zaten hatırlayabildiğimden beri ve bu bir süre geri gidiyor) olmuştur. Onlar başvuran iki dizin girişleri olan tam aynı temel verileri. Bir dosyadaki veriler onun tarafından belirtilir inode
. Bir dosya sistemindeki her dosya bir inode'yu işaret eder, ancak her dosyanın benzersiz bir inode'a işaret etmesi gerekmez - bu, zor bağlantıların geldiği yerdir.
İnode'lar yalnızca belirli bir dosya sistemi için benzersiz olduğundan, sabit bağlantıların aynı dosya sisteminde olması zorunludur (sembolik bağlantıların aksine). Sembolik bağların aksine, ayrıcalıklı bir dosya olmadığına - hepsinin eşit olduğuna dikkat edin. Veri alanı, yalnızca bu inode'u kullanan tüm dosyalar silindiğinde serbest bırakılacaktır (ve tüm işlemler onu kapatır, ancak bu farklı bir konudur).
"ls -i"
Komutu belirli bir dosyanın inode'unu almak için kullanabilirsiniz . "find <filesystemroot> -inum <inode>"
Komutu, dosya sistemindeki tüm dosyaları verilen inode ile bulmak için kullanabilirsiniz .
İşte tam olarak bunu yapan bir senaryo. Şunu çağırdın:
findhardlinks ~/jquery.js
ve o dosya sistemi için, o dosya için bağlantı kuran tüm dosyaları bulacaktır:
pax@daemonspawn:~# ./findhardlinks /home/pax/jquery.js
Processing '/home/pax/jquery.js'
'/home/pax/jquery.js' has inode 5211995 on mount point '/'
/home/common/jquery-1.2.6.min.js
/home/pax/jquery.js
İşte senaryo.
#!/bin/bash
if [[ $# -lt 1 ]] ; then
echo "Usage: findhardlinks <fileOrDirToFindFor> ..."
exit 1
fi
while [[ $# -ge 1 ]] ; do
echo "Processing '$1'"
if [[ ! -r "$1" ]] ; then
echo " '$1' is not accessible"
else
numlinks=$(ls -ld "$1" | awk '{print $2}')
inode=$(ls -id "$1" | awk '{print $1}' | head -1l)
device=$(df "$1" | tail -1l | awk '{print $6}')
echo " '$1' has inode ${inode} on mount point '${device}'"
find ${device} -inum ${inode} 2>/dev/null | sed 's/^/ /'
fi
shift
done
. ./findhardlinks.bash
OS X’in Zsh’ındayken başlıyorum . Ekrandaki geçerli pencerem kapanıyor.
INUM=$(stat -c %i $1)
. Ayrıca NUM_LINKS=$(stat -c %h $1)
. man stat
Kullanabileceğiniz daha fazla format değişkeni için görün .
ls -l
İlk sütun izinleri temsil edecektir. İkinci sütun, alt öğelerin sayısı (dizinler için) veya dosyaya aynı verilere giden yolların sayısı (orijinal dosya dahil olmak üzere sabit bağlantılar) olacaktır. Örneğin:
-rw-r--r--@ 2 [username] [group] [timestamp] HardLink
-rw-r--r--@ 2 [username] [group] [timestamp] Original
^ Number of hard links to the data
inode
hangisinin disk içeriğini gösterdiğine işaret eder.
Aşağıdaki daha basit olana ne dersiniz? (İkincisi, yukarıdaki uzun komut dosyalarının yerini alabilir!)
Belirli bir dosyanız varsa <THEFILENAME>
ve dizine yayılmış olan tüm hardlinks bağlantılarını bilmek istiyorsanız <TARGETDIR>
, (ki bu, tüm sistem tarafından bile belirtilebilir /
)
find <TARGETDIR> -type f -samefile <THEFILENAME>
<SOURCEDIR>
Birden fazla sabit bağlantıya sahip tüm dosyaları bilmek istiyorsanız, mantığı genişletme <TARGETDIR>
:
find <SOURCEDIR> -type f -links +1 \
-printf "\n\n %n HardLinks of file : %H/%f \n" \
-exec find <TARGETDIR> -type f -samefile {} \;
-type f
çünkü dosya da bir dizin olabilir.
.
Ve ..
dizinleri girişler hardlinks bulunmaktadır. Bir dizinde kaç tane alt dizin olduğunu, link sayısından öğrenebilirsiniz .
. Yine de find -samefile .
herhangi bir subdir/..
çıktı yazdırmayacağından , bu durum yine de tartışmalı . find
(en azından GNU versiyonu) ..
bile olsa görmezden gelmek zor kodlanmış görünüyor -noleaf
.
O(n^2)
çalışır ve çalışır find
. find ... -printf '%16i %p\n' | sort -n | uniq -w 16 --all-repeated=separate
çalışacak, (16, 2 ^ 63-1 ondalık gösterimi için yeterince geniş değil, bu yüzden XFS dosya sisteminiz çok yüksek inode sayılarına sahip olacak kadar büyük olduğunda, dikkat edin)
Bir dosya sistemindeki tüm sabit bağlantıları bulmak için komut dosyalarıyla ilgili birçok cevap vardır. Birçoğu çalışan gibi aptalca şeyler yaparlar -samefile
, EACH çarpı bağlantılı dosyanın tüm dosya sistemini taramak için . Bu çılgınca; İhtiyacınız olan tek şey inode numarasını sıralamak ve kopyaları yazdırmak.
Tüm hardlinked dosya setlerini bulmak ve gruplandırmak için sadece bir dosya sistemi üzerinden geçiş
find dirs -xdev \! -type d -links +1 -printf '%20D %20i %p\n' |
sort -n | uniq -w 42 --all-repeated=separate
Bu, çok sayıda hardlinked dosya kümesi bulmak için diğer cevaplardan çok daha hızlıdır .
find /foo -samefile /bar
sadece bir dosya için mükemmel.
-xdev
: bir dosya sistemi ile sınır. FS-id'i uniq on olarak da yazdığımızdan kesinlikle gerek yok.! -type d
dizinleri reddetme: .
ve ..
girişleri her zaman bağlantılı oldukları anlamına gelir.-links +1
: bağlantı kesinlikle > 1
-printf ...
FS kimliği, inode numarası ve yolu yazdır. (Söyleyebileceğimiz sabit sütun genişliklerine dolguyla uniq
.)sort -n | uniq ...
nümerik sıralama ve ilk 42 sütunda birleştirme, grupları boş bir çizgiyle ayırmaKullanma ! -type d -links +1
, sıralama girişinin yalnızca uniq'in son çıktısı kadar büyük olduğu anlamına gelir, bu nedenle çok fazla miktarda dize işlemi yapmıyoruz. Tabi yalnızca bir dizi hardlinks içeren bir alt dizinde çalıştırmazsanız. Neyse, bu dosya sisteminde dolaşan diğer tüm çözümlerden daha az LOT daha az CPU zamanı kullanacak.
örnek çıktı:
...
2429 76732484 /home/peter/weird-filenames/test/.hiddendir/foo bar
2429 76732484 /home/peter/weird-filenames/test.orig/.hiddendir/foo bar
2430 17961006 /usr/bin/pkg-config.real
2430 17961006 /usr/bin/x86_64-pc-linux-gnu-pkg-config
2430 36646920 /usr/lib/i386-linux-gnu/dri/i915_dri.so
2430 36646920 /usr/lib/i386-linux-gnu/dri/i965_dri.so
2430 36646920 /usr/lib/i386-linux-gnu/dri/nouveau_vieux_dri.so
2430 36646920 /usr/lib/i386-linux-gnu/dri/r200_dri.so
2430 36646920 /usr/lib/i386-linux-gnu/dri/radeon_dri.so
...
TODO ?: çıktıyı awk
veya ile açın cut
. uniq
Alan seçimi desteği çok sınırlı, bu yüzden bulma çıktısını dolduruyorum ve sabit genişlikte kullanıyorum. 20char, mümkün olan maksimum inode veya cihaz numarası için yeterince geniştir (2 ^ 64-1 = 18446744073709551615). XFS, diskte nereye yerleştirildiğine bağlı olarak inode sayılarını seçer, 0'dan bitişik değil, bu yüzden büyük XFS dosya sistemlerinde milyarlarca dosya olmasa bile> 32bit inode numaralarına sahip olabilir. Diğer dosya sistemlerinde devasa olmasalar bile 20 basamaklı inode numaraları bulunabilir.
TODO: yinelenen grupları yola göre sırala. Bunları bağlama noktasına göre sıraladıktan sonra inode numarası, çok sayıda sabit bağlantı içeren birkaç farklı alt diziniz varsa, bunları bir araya getirir. (yani, dup grup grupları bir araya gelirler, fakat çıktı onları karıştırır).
Bir son sort -k 3
satır, satır gruplarını tek bir kayıt olarak değil, satırları ayrı ayrı sıralar. Bir çift yeni satırı bir NUL baytına dönüştürecek bir şeyle ön işleme koymak ve GNU kullanmak sort --zero-terminated -k 3
hile yapabilir. tr
2 -> 1 veya 1-> 2 kalıpları değil, yalnızca tek karakterlerde çalışır. perl
bunu yapardı (veya sadece perl veya awk içinde ayrıştırır ve sıralarlar). sed
ayrıca çalışabilir.
%D
Dosya sistemi tanıtıcısı (hiçbir dosya sistemleri ise o geçerli önyükleme için benzersiz olduğunu umount
, bu nedenle aşağıdaki daha genel ed) 'dir: find directories.. -xdev ! -type d -links +1 -printf '%20i %20D %p\n' | sort -n | uniq -w 42 --all-repeated=separate
. Bu, hiçbir dizinin dosya sistemi düzeyinde başka bir dizin içermediği sürece çalışır, aynı zamanda sabitlenmiş olabilecek her şeye bakar (cihazlar veya yazılım bağlantıları - evet, yazılım bağlantıları 1'den büyük bir bağlantı sayısına sahip olabilir). dev_t
Ve ino_t
bugün 64 bit uzun olduğuna dikkat edin . Bu olasılık 64 bit sistemimiz olduğu sürece geçerli olacak.
! -type d
yerine kullanmanın kullanımıyla ilgili harika bir nokta -type f
. Hatta dosya sistemimde bazı dosya koleksiyonları düzenlemekten bazı sabit linkler bile var. Cevabınızı gelişmiş sürümünüzle güncelledik (ama önce fs-id'yi koydum, bu yüzden sıralama düzeni en azından dosya sistemine göre gruplandı.)
Bu, Torocoro-Macho'nun kendi cevabı ve senaryosuna yapılan bir yorumdan kaynaklanıyor, ancak kesinlikle yorum kutusuna sığmayacak.
Komut dosyanızı bilgileri bulmak için daha basit yollarla ve böylece daha az işlem çağrısı ile yeniden yazdınız.
#!/bin/sh
xPATH=$(readlink -f -- "${1}")
for xFILE in "${xPATH}"/*; do
[ -d "${xFILE}" ] && continue
[ ! -r "${xFILE}" ] && printf '"%s" is not readable.\n' "${xFILE}" 1>&2 && continue
nLINKS=$(stat -c%h "${xFILE}")
if [ ${nLINKS} -gt 1 ]; then
iNODE=$(stat -c%i "${xFILE}")
xDEVICE=$(stat -c%m "${xFILE}")
printf '\nItem: %s[%d] = %s\n' "${xDEVICE}" "${iNODE}" "${xFILE}";
find "${xDEVICE}" -inum ${iNODE} -not -path "${xFILE}" -printf ' -> %p\n' 2>/dev/null
fi
done
Kolay karşılaştırma için olabildiğince benzer tutmaya çalıştım.
$IFS
Eğer bir glob yeterse, sihirden kaçınılmalıdır , çünkü gereksiz yere kıvrımlıdır ve dosya isimleri aslında yeni satırlar içerebilir (fakat uygulamada çoğunlukla birinci sebep).
El ile ayrıştırmaktan ls
ve bu tür çıktılardan mümkün olduğu kadar kaçınmalısınız , çünkü er ya da geç ısırır. Örneğin: ilk awk
satırınızda boşluk içeren tüm dosya adlarında başarısız olursunuz.
printf
%s
Sözdizimi ile çok sağlam olduğu için sık sık sonunda sıkıntıları kurtaracak . Ayrıca, çıktı üzerinde tam kontrol sağlar ve aksine, tüm sistemler arasında tutarlıdır echo
.
stat
Bu durumda size çok fazla mantık kazandırabilir.
GNU find
güçlü.
Siz head
ve tail
çağrılarınız awk
, örneğin exit
komut ve / veya NR
değişkeni seçerek doğrudan ele alınabilirdi . Bu, neredeyse her zaman ciddi şekilde çalışan komut dosyalarında daha iyi performans gösteren betimleme işlemlerini koruyacaktır.
Senin egrep
de olabildiğince iyi olabilir grep
.
find ... -xdev -type f -links +1 -printf '%16i %p\n' | sort -n | uniq -w 16 --all-repeated=separate
. Bu sadece bir kerelik fs geçerken ÇOK daha hızlı. Aynı anda birden fazla FS için, inode numaralarını bir FS kimliği ile öneklemeniz gerekir. Belki defind -exec stat... -printf ...
findhardlinks
Senaryoya göre (yeniden adlandırılmış hard-links
), yeniden düzenledim ve çalışmasını sağladım.
Çıktı:
# ./hard-links /root
Item: /[10145] = /root/.profile
-> /proc/907/sched
-> /<some-where>/.profile
Item: /[10144] = /root/.tested
-> /proc/907/limits
-> /<some-where else>/.bashrc
-> /root/.testlnk
Item: /[10144] = /root/.testlnk
-> /proc/907/limits
-> /<another-place else>/.bashrc
-> /root/.tested
# cat ./hard-links
#!/bin/bash
oIFS="${IFS}"; IFS=$'\n';
xPATH="${1}";
xFILES="`ls -al ${xPATH}|egrep "^-"|awk '{print $9}'`";
for xFILE in ${xFILES[@]}; do
xITEM="${xPATH}/${xFILE}";
if [[ ! -r "${xITEM}" ]] ; then
echo "Path: '${xITEM}' is not accessible! ";
else
nLINKS=$(ls -ld "${xITEM}" | awk '{print $2}')
if [ ${nLINKS} -gt 1 ]; then
iNODE=$(ls -id "${xITEM}" | awk '{print $1}' | head -1l)
xDEVICE=$(df "${xITEM}" | tail -1l | awk '{print $6}')
echo -e "\nItem: ${xDEVICE}[$iNODE] = ${xITEM}";
find ${xDEVICE} -inum ${iNODE} 2>/dev/null|egrep -v "${xITEM}"|sed 's/^/ -> /';
fi
fi
done
IFS="${oIFS}"; echo "";
Bir GUI çözümü sorunuza gerçekten yaklaşıyor:
Asıl sabitlenmiş dosyaları "ls" den listeleyemezsiniz, çünkü önceki yorumcuların işaret ettiği gibi, "names" dosyası aynı verinin diğer adıdır. Bununla birlikte, gerçekte istediklerinize gerçekten yaklaşan bir GUI aracı vardır ki bu linux altında aynı verilere (hardlinks gibi) işaret eden dosya adlarının yol listesini görüntüler, buna FSLint denir. İstediğiniz seçenek "Ad çakışmaları" -> Arama (XX) -> 'daki "onay kutusu $ PATH" seçeneğinin işaretini kaldırın ve açılır kutudan "for ..." dan sonra üst ortaya doğru "Aliases" ı seçin.
FSLint çok kötü bir şekilde belgelenmiştir ancak "Arama yolu" altındaki sınırlı dizin ağacının "Tekrarla?" ve yukarıda belirtilen seçeneklerde, program araştırmasından sonra, aynı veriye işaret eden yollar ve isimlerle bağlantılı, sabitlenmiş verilerin bir listesi üretilir.
ls
Bir 'takma ad' kullanarak sabit bağlantıları vurgulamak için yapılandırabilirsiniz , ancak daha önce de belirtildiği gibi, hardlink'in kaynağını göstermenin bir yolu yoktu, bu yüzden bu konuda .hardlink
yardımcı olmayı düşünüyorum.
Aşağıdakileri telefonunuzda bir yere ekleyin. .bashrc
alias ll='LC_COLLATE=C LS_COLORS="$LS_COLORS:mh=1;37" ls -lA --si --group-directories-first'
link(2)
sistem çağrısından sonra , hangisinin orijinal ve diğeri bağlantı olduğu hiçbir anlamı yoktur. Bu nedenle, cevapların işaret ettiği gibi, tüm bağlantıları bulmanın tek yolu budurfind / -samefile /a/A
. Çünkü bir inode için bir dizin girişi aynı inode için diğer dizin girişlerini "bilmez". Yaptıkları tek şey inode'yu yeniden saymak, böylece soyadı ne zaman silinebiliyorunlink(2)ed
. (Buls
çıktıdaki "link sayısı" dır ).