76

I know of this command:

find /path/to/mountpoint -inum <inode number>

but it is a very slow search, I feel like there has to be a faster way to do this. Does anybody know a faster method?

8
  • 1
    This is my first time seeing a search using inode. When do you need to search by inode ?
    – Coren
    Commented Mar 29, 2012 at 8:53
  • 1
    @Coren - it's commonly used if you have a file with, say, a "-" in front. You can do ls -li to find the inode of it, then: find . -inum <inode> -exec rm -i {} \; This is a belt-and-bracers approach to ensuring you can remove the file. Of course, you could also 'rm -- -filename', or rm ./-filename, or rm "-filename". Commented Mar 29, 2012 at 10:51
  • 5
    @Coren with selinux, log messages include the inode, but not the full path. So you have to search for the inode to find the file being referred to. (thats my use case anyway)
    – phemmer
    Commented Mar 29, 2012 at 13:30
  • 1
    @Coren For example when a file has multiple hard links, you've spotted that the contents are obsolete and want to delete the file, but you've only found one of the file's names and want to delete the others. Commented Mar 29, 2012 at 22:21
  • 4
    Just use find / -inum <inode>. It is much more portable than debugfs and also works much more reliably (it can find paths that are not belonging to files on the hard drive, like devices, for instance).
    – 7heo.tk
    Commented Apr 2, 2015 at 16:30

5 Answers 5

54

For an ext4 filesystem, you can use debugfs as in the following example:

$ sudo debugfs -R 'ncheck 393094' /dev/sda2 2>/dev/null
Inode   Pathname
393094  /home/enzotib/examples.desktop

The answer is not immediate, but seems to be faster than find.

The output of debugfs can be easily parsed to obtain the file names:

$ sudo debugfs -R 'ncheck 393094' /dev/sda2 | cut -f2 | tail -n2 > filenames
4
  • 1
    I should probably have specified the filesystem type. It didn't occur to me that the method of doing these things would be different for different filesystems. I'm using XFS, so while I'm sure your answer is correct, it won't help me specifically.
    – Alex
    Commented Mar 30, 2012 at 7:39
  • This returned nothing for me. Commented Sep 2, 2020 at 5:26
  • 2
    Doesn't work on an encrypted drive: debugfs: Bad magic number in super-block while trying to open /dev/sda2 /dev/sda2 contains a crypto_LUKS file system ncheck: Filesystem not open Commented Feb 5, 2021 at 3:12
  • 3
    @LaneRettig You have to run it on the file system device, not the container device. This will be something like /dev/mapper/sda2_crypt.
    – Boann
    Commented Nov 28, 2022 at 15:09
18

btrfs

man btrfs-inspect-internal says:

   inode-resolve [-v] <ino> <path>
       (needs root privileges)

       resolve paths to all files with given inode number ino in a given
       subvolume at path, ie. all hardlinks

       Options

       -v
           verbose mode, print count of returned paths and ioctl()
           return value

Example:

  • sudo btrfs inspect-internal inode-resolve 15380 /home
5
  • Note: this needs installing (on Ubuntu anyway). Commented Sep 2, 2020 at 18:40
  • Sridhar what package was it for the benefit of other Ubuntuers?
    – Tom Hale
    Commented Sep 3, 2020 at 3:32
  • I believe it's sudo apt install btrfs-tools but I haven't verified it mysellf. fsck had already destroyed half my files before I realized I could check which inodes it was going to "fix" so never tried it out. Commented Sep 4, 2020 at 18:30
  • 2
    Is this instantaneous like searching an indexed record, or does it take time that is proportional to the number of files in the path like searching for a file name? Commented Nov 27, 2020 at 12:51
  • 2
    @DamnVegetables - just tried this and it worked almost instantaneously on a fairly large subvolume. Commented Feb 19, 2023 at 0:08
4

The basic problem is that there is no index in most filesystems that work in this direction. If you need to do this kind of thing frequently your best bet is to set up a scheduled task that scans the filesystem for the information you need, create a database (using sqlite3 for example) which has the information you need and create an index on the inode number to locate file(s) quickly.


Example:

#!/bin/bash

# Generate an index file 

# 
SCAN_DIRECTORY=/
DB_DIRECTORY=~/my-sqlite-databases
if [ ! -d ${DB_DIRECTORY} ] ; then
    mkdir ${DB_DIRECTORY}
fi

# Remove any old database - or use one created with a filename based on the date
rm ${DB_DIRECTORY}/files-index.db

(
# Output a command to create a table file_info in the database to hold the information we are interested in
echo 'create table file_info ( inode INTEGER, filepath, filename, numlinks INTEGER, size INTEGER);'

# Use find to scan the directory and locate all the objects - saving the inode, file path, file name, number of links and file size
# This could be reduced to just the inode, file path and file name ... if you are looking for files with multiple links the numlinks is useful (select * from file_info where numlinks > 1)

# Find output formats
#
# %i = inode
# %h = path to file (directory path)
# %f = filename (no directory path)
# %n = number of hard links
# %s = size

# Use find to generate the SQL commands to add the data to the database table.

find $SCAN_DIRECTORY -printf "insert into file_info (inode, filepath, filename, numlinks, size) values ( %i, '%h', '%f', %n, %s);\n"

# Finally create an index on the inode number so we can locate values quickly

echo 'create index inode_index on file_info(inode);'

# Pipe all the above commands into sqlite3 and have sqlite3 create and populate a database
) | sqlite3 ${DB_DIRECTORY}/files-index.db

# Once you have this in place, you can search the index for an inode number as follows

echo 'select * from file_info where inode = 1384238234;' | sqlite3 ${DB_DIRECTORY}/files-index.db
1
  • This method could be implemented into locate (which may actually be mlocate or plocate) with the advantage that the filesystem needs to be scanned only once and databases are updated very fast if only few files have changed.
    – Juergen
    Commented Jan 23 at 19:40
4

For XFS this seems to be done using xfs_db(1) and the blockget and ncheck commands:

blockget [-npvs] [-b bno] ... [-i ino] ...
Get block usage and check filesystem consistency. The information is saved for use by a subsequent blockuse, ncheck, or blocktrash command. See xfs_check(8) for more information.

ncheck [-s] [-i ino] ...
Print name-inode pairs. A blockget -n command must be run first to gather the information.

Example:

# xfs_db -c 'blockget -n -i 123456' /dev/sde1
inode 123456 add link, now 1
inode 123456 mode 0100644 fmt extents afmt extents nex 1 anex 0 nblk 1 sz 135
inode 123456 nlink 6 not dir
inode 123456 extent [0,822682790,1,0]
setting inode to 6594903486 for block 3/17376422
inode 123456 add link, now 2
inode 123456 add link, now 3
inode 123456 add link, now 4
inode 123456 add link, now 5
inode 123456 add link, now 6
inode 123456 name dir/subdir/foo.bar
1
  • 1
    I tried -c 'blockget -n -i 6594903486' -c 'ncheck -i 6594903486', but it does not add relevant information by using ncheck, too. The -n flag of blockget returns already the filename. PS Works only if the filesystem is unmounted, is slow as well (not sure if as slow as find) and returns only one filename, even if multiple hardlinks exist (find even returns hardlinks).
    – mgutt
    Commented Mar 12, 2022 at 12:54
2

You could look at the fsdb command, found on most Unices, and available somewhere for Linux I am sure. This is a powerful command allowing you to to access the in-core inode structure of files, so be careful. The syntax is also very terse.

fsdb for AIX

fsdb re-link file on Solaris

While fsdb won't actually let you discover the filename of the inode, it does allow you to directly access the inode when you specify it, in essence "porting" you to the file itself (or at least it's data block pointers) so it's quicker in that respect than the find ;-).
Your question doesn't specify what you want to do with the file. Are you perchance decoding NFS filehandles?

sc.

2
  • 1
    Well, I didn't think what I was going to do with the information was relevant to my question, so I left it out. In my case, it was merely a curiosity question; my xfs_fsr defragmentation spits out which inodes it defragments, and one was extremely fragmented (over 5000 extents) and I was just curious which file it was. find works, it's just so slow.
    – Alex
    Commented Mar 30, 2012 at 7:48
  • I'm trying to fix a problem where my rhel vm does a full (20 minute!) fsck every boot and all I've got to go on is the inode number reported in /var/opt/messages as faulty. (Having said that, find -inum didn't actually find it)
    – user13757
    Commented Sep 20, 2017 at 16:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .