วิธีการพกพาเพื่อค้นหาหมายเลขไอโหนด


10

ตอนแรกฉันใช้stat -c %i file(เพื่อตรวจจับการปรากฏตัวของคุก ) ซึ่งดูเหมือนว่าจะทำงานกับการกระจาย Linux ใด ๆ ภายใต้ดวงอาทิตย์ บน OS X' ls -i file | cut -d ' ' -f 1ผมต้องใช้

มีวิธีการบางอย่างเพื่อหาหมายเลขไอโหนดของไฟล์ในสคริปต์เชลล์ซึ่งเป็นแบบพกพาข้ามแพลตฟอร์มระวัง * และไม่ได้ขึ้นอยู่กับตามอำเภอใจฉาวโฉ่ls?


1
คุณอาจจะสนใจหรือมีคำตอบที่ดีกว่าสำหรับฉันจะบอกได้อย่างไรว่าฉันทำงานเป็น chroot? .
Gilles 'หยุดความชั่วร้าย'

คุณสามารถอธิบายรายละเอียดเกี่ยวกับ "ls capricious ls" ได้หรือไม่?
jlliagre

@jlliagre: คนอื่นทำได้ดีกว่านี้แล้ว
l0b0

โอเคสำหรับไฟล์ดังกล่าวดูคำตอบของฉัน
jlliagre

คำตอบ:


11

ทางออกที่เป็นไปได้: ข้อมูลจำเพาะ POSIX สำหรับการlsระบุ-iดังนั้นอาจเป็นแบบพกพา มีใครรู้บ้างเกี่ยวกับการใช้งานที่เป็นที่นิยมlsซึ่งไม่สนับสนุนสิ่งนี้หรือพิมพ์ในวิธีที่ต่างจากตัวอย่างต่อไปนี้:

$ ls -di /
2 /

3
@jlliagre: โปรดอ่านก่อนโพสต์ statคำสั่งไม่ได้ทำงานบน OS X, ls -diทำงานได้ทั้งบน
l0b0

1
แม้แต่ Busybox lsก็มี-dและ-iเป็นคุณสมบัติบังคับ (แม้ว่าlsตัวมันเองนั้นเป็นตัวเลือก
Gilles 'หยุดความชั่วร้าย'

1
ไมเคิลเข้าใจผิดเป็นสิ่งที่ฉันแสดงความคิดเห็น มันไม่คุ้มค่ากับความคิดเห็นที่ "อ่านก่อนโพสต์" ที่ค่อนข้างหยาบและไม่สมควร
jlliagre

2
มีเป็นข้อยกเว้นนี้: lsกับ-iด้านหน้าแผ่นที่มีช่องว่างอย่างน้อย Solaris 10 (อาจ Solaris 11 ผมยังไม่ได้ตรวจสอบ) ดูเหมือนว่านี่เป็นพฤติกรรมดั้งเดิมที่กลับไปเป็นรุ่น Unix 7 ดังนั้นฉันจึงสงสัยว่าหลาย ๆ องค์กร * ระวังรสชาติยังคงรักษาพฤติกรรมนี้ไว้ (ฉันมีเพียง Solaris 10 เท่านั้น) ใกล้ที่ฉันสามารถบอกได้ว่าถ้าคุณใช้บางสิ่งบางอย่างที่กำหนดเขตข้อมูลอย่างถูกต้องในช่องว่างโดยพลการ (เช่นไม่ใช่cutแต่ตัวอย่างawkหรือเพียงแค่การแยกฟิลด์ของเชลล์เอง) มันเป็นแบบพกพาที่คาดหวังว่าสตริงที่ไม่ใช่ช่องว่างแรกจำนวน.
mtraceur

1
@ l0b0 ใช่ มันต้องมีการอุทิศตนอย่างร้ายกาจ: การศึกษา / ทดสอบและการท่องจำจำนวนมากเพื่อผลตอบแทนที่ลดลงอย่างต่อเนื่อง เป็นไปได้อย่างน้อยก็สำหรับคำจำกัดความของ "พกพา" แต่ก็ไม่ได้เป็นประสบการณ์ที่น่าพึงพอใจ
mtraceur

2

สิ่งนี้ควรเป็นแบบพกพาและทำงานกับชื่อไฟล์ที่มีช่องว่าง, การขึ้นบรรทัดใหม่หรืออักขระแปลก ๆ อื่น ๆ ที่นำไปสู่พฤติกรรม ls ตามอำเภอใจ

filename="whatever file name"
find . -name "$filename" -exec sh -c 'ls -di "$0" | head -1' {} \;

1

เพื่อเพิ่มความสะดวกในการพกพาคุณอาจใช้ฟังก์ชั่น wrapper เฉพาะแพลตฟอร์ม (ที่นี่เรียกว่าstatinode()) รอบstatคำสั่งที่สามารถขึ้นอยู่กับเอาท์พุทของuname -s(ดูuname )

ls จะต้องใช้เป็นตัวเลือกสำรองเท่านั้น

(
shopt -s nocasematch nullglob    # using Bash
case "$(uname -s)" in
   # nocasematch alternative
   #[Ll][Ii][Ni][Uu][Xx]   )  statinode() { stat -c '%i' "$@"; return 0; };;
   "Linux"   )      statinode() { stat -c '%i' "$@"; return 0; };;
   "Darwin"  )      statinode() { stat -f '%i' "$@"; return 0; };;
   "FreeBSD" )      statinode() { stat -f '%i' "$@"; return 0; };;
           * )      statinode() { ls -id "$@" | cut -d ' ' -f 1; return 0; };;
esac
#export -f statinode
statinode / / / /
shopt -u nocasematch nullglob
)

0

statเป็นส่วนหนึ่งของแพ็คเกจGNU Coreutils OSX ใช้การใช้งานที่แตกต่างกันstat(น่าจะเป็นแบบ BSD) ซึ่งไม่ได้ใช้อาร์กิวเมนต์บรรทัดคำสั่งเดียวกัน

คุณสามารถติดตั้ง GNU Coreutils บน OSX ได้ตลอดเวลา แน่นอนว่าไม่ช่วยถ้าคุณต้องการโซลูชันที่ทำงานบนระบบ OSX ที่ไม่มี GNU Coreutils

หรือถ้าฉันอ่านman page stat ของ OSXอย่างถูกต้องstat -f %i fileบน OSX จะทำงานเหมือนกับการstat -c %i fileใช้เวอร์ชั่น Coreutils (การพิจารณาว่ารุ่นของstatคุณมีเป็นอีกเรื่องหนึ่งคุณลองได้stat --version >/dev/nullถ้าสำเร็จคุณก็มีรุ่น GNU Coreutils)

การls -diแก้ปัญหาเป็นแบบพกพามากขึ้นและปัญหาน้อยลง แต่นี่เป็นทางเลือก


0

ทางออกอื่น:

#!/usr/bin/perl

use strict;
use warnings;

die "Usage: $0 filename\n" if scalar @ARGV != 1;
my $file = $ARGV[0];
my @stat = stat $file;
die "$file: $!\n" if not @stat;
print "$stat[1]\n";

คุณสามารถสันนิษฐานได้ว่าติดตั้ง Perl อย่างปลอดภัยแล้ว


0

คล้ายกับแนวทางของเจฟฟ์statสามารถทดสอบได้โดยตรงเช่นกัน

(
if (stat -c '%i' / 1>/dev/null 2>&1; exit $?); then
   statinode() { stat -c '%i' "$@"; return 0; }
elif (stat -f '%i' / 1>/dev/null 2>&1; exit $?); then
   statinode() { stat -f '%i' "$@"; return 0; }
elif test -n "$(exec 2>/dev/null; ls -id / | cut -d ' ' -f 1)"; then
   statinode() { ls -id "$@" | cut -d ' ' -f 1; return 0; }
else
   echo 'Could not create statinode(). Exiting ...' && exit 1
fi
# export -f statinode
statinode / / / /
declare -f statinode
)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.