LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   script <syntax> for finding all hardlinks in a directory (https://www.linuxquestions.org/questions/linux-newbie-8/script-syntax-for-finding-all-hardlinks-in-a-directory-4175435624/)

harrytapp 11-04-2012 05:17 PM

script <syntax> for finding all hardlinks in a directory
 
I have been given a task with out all supporting information...

Identify all the hard links that are located in the directory "/sbin". This may not be obvious to derive, but you can use "piping" to create a command chain. You can look at the on-line documentation to determine which command options are needed. Here's the list of commands that can be used to list the duplicate inodes (Index Nodes):
ls use the "print index number (inode)" option
cut use the options:
use a space character as a field delimiter select the first field
sort use the "compare as a general numerical value" option
uniq use the "only print duplicate lines" option
Once you obtain the "duplicate" inodes, use an "ls" command with the "list inodes" option, piping the output into "grep", searching for the inodes listed. You'll need to repeat this process for each of the individual inodes that are listed.

Can any one help me?
I know that the '/sbin' directory does not have many (if any) hardlinks, so if you know of a directory that has a handfull in Manriva 2011 would be helpfull as well.

GlennsPref 11-04-2012 06:21 PM

Code:

ls -lai /sbin | grep lrw > /home/glenn/build/sbinlinks.txt
list files, -longnames -all -inodes of the folder /sbin and

| pipe the list through grep displaying any lines that have a string "lrx" (link, read, execute)

and > redirect the output to a text file. The .txt file will be created.

to concatenate use >> (writes to end of existing file)

Some other tools you might try, symlinks and ldconfig.
Code:

ls --help
symlinks --help
ldconfig --help

You may need to be root to access those apps.

If you'd like to practice more check out the ibm dev website,

btw,
Quote:

Hi, Welcome to LQ!

LQ has a fantastic search function that may save you time waiting for an answer to a popular question.

With over 4 million posts to search it's possible the answer has been given.
:)

Regards Glenn

chrism01 11-04-2012 06:57 PM

I suggest you do the reading suggested in your instructions; sounds a lot like homework https://www.linuxquestions.org/linux/rules.html.

At least attempt to solve it, one step at a time.
If you still get stuck, post what you've got so far (code) & what the apparent problem is.

Valery Reznic 11-05-2012 03:43 AM

Quote:

Originally Posted by GlennsPref (Post 4822196)
Code:

ls -lai /sbin | grep lrw > /home/glenn/build/sbinlinks.txt
list files, -longnames -all -inodes of the folder /sbin and

| pipe the list through grep displaying any lines that have a string "lrx" (link, read, execute)

and > redirect the output to a text file. The .txt file will be created.

to concatenate use >> (writes to end of existing file)

Some other tools you might try, symlinks and ldconfig.
Code:

ls --help
symlinks --help
ldconfig --help

You may need to be root to access those apps.

If you'd like to practice more check out the ibm dev website,

btw,



Regards Glenn

Your solution will find softlinks. And OP asked for hard links.

In order to find hard links I suggest to use 'stat'

harrytapp 11-05-2012 04:42 PM

First I would like to Thank You for your time and effort to help me!!!
Unfortunately the script forces print to file symbolic links only (ln -s)
I was looking for objects that have the same inode numbers on the file system...I created a testing structure
[root@localhost a]# pwd
/harry/a
[root@localhost a]# touch a1
[root@localhost a]# ls -lia
683358 -rw-r--r-- 1 root root 0 Nov 5 14:11 a1
[root@localhost a]# ln a1 /harry/a/a1
ln: failed to create hard link `/harry/a/a1': File exists
(just proving that you can't create a hardlink with the same name in the same directory)
[root@localhost a]# ln a1 /harry/a/a2
[root@localhost a]# ls -lia
683358 -rw-r--r-- 2 root root 0 Nov 5 14:11 a1
683358 -rw-r--r-- 2 root root 0 Nov 5 14:11 a2
[root@localhost a]# cd ..
[root@localhost harry]# cd b
[root@localhost b]# ln /harry/a/a1 a3
[root@localhost b]# ls -lia
683358 -rw-r--r-- 3 root root 0 Nov 5 14:11 a3
[root@localhost b]# ln /harry/a/a1 a4
[root@localhost b]# ls -lia
683358 -rw-r--r-- 4 root root 0 Nov 5 14:11 a3
683358 -rw-r--r-- 4 root root 0 Nov 5 14:11 a4

It would be nice if I could print only inode numbers that have hardlinks on the file system...ie
search in /harry including subfolders
683358 -rw-r--r-- 2 root root 0 Nov 5 14:11 /harry/a/a1:/harry/a/a2:/harry/b/a3:/harry/b/a4
Thank You.

Valery Reznic 11-06-2012 10:03 AM

Quote:

Originally Posted by harrytapp (Post 4822962)
First I would like to Thank You for your time and effort to help me!!!
Unfortunately the script forces print to file symbolic links only (ln -s)
I was looking for objects that have the same inode numbers on the file system...I created a testing structure
[root@localhost a]# pwd
/harry/a
[root@localhost a]# touch a1
[root@localhost a]# ls -lia
683358 -rw-r--r-- 1 root root 0 Nov 5 14:11 a1
[root@localhost a]# ln a1 /harry/a/a1
ln: failed to create hard link `/harry/a/a1': File exists
(just proving that you can't create a hardlink with the same name in the same directory)
[root@localhost a]# ln a1 /harry/a/a2
[root@localhost a]# ls -lia
683358 -rw-r--r-- 2 root root 0 Nov 5 14:11 a1
683358 -rw-r--r-- 2 root root 0 Nov 5 14:11 a2
[root@localhost a]# cd ..
[root@localhost harry]# cd b
[root@localhost b]# ln /harry/a/a1 a3
[root@localhost b]# ls -lia
683358 -rw-r--r-- 3 root root 0 Nov 5 14:11 a3
[root@localhost b]# ln /harry/a/a1 a4
[root@localhost b]# ls -lia
683358 -rw-r--r-- 4 root root 0 Nov 5 14:11 a3
683358 -rw-r--r-- 4 root root 0 Nov 5 14:11 a4

It would be nice if I could print only inode numbers that have hardlinks on the file system...ie
search in /harry including subfolders
683358 -rw-r--r-- 2 root root 0 Nov 5 14:11 /harry/a/a1:/harry/a/a2:/harry/b/a3:/harry/b/a4
Thank You.


Why do you want to mess with inode numbers? stat can give you all needed information.
Code:

%F - file type
 %h - number of links
 %n (or %N) - file name

Please note that '%h' for directories report not number of hard links, but number of entries in this directory.

So, you can run
Code:

stat -c "%F %h %N" /your_directory
You need only entries where "%F" is "regular file" and %h > 1

So something like this should do:
Code:

stat -c "%F %h %N" /your_directory | awk '{if ( ($1 == "regular") && ($2 == "file") && ($3 > 1) ) print $0 }'
If you want make it recursive you can use find + stat

fpmurphy 11-06-2012 10:41 AM

Assuming you are in /sbin
Code:

ls -l |  awk '$2 > 1 { print $2, $9 }'

harrytapp 11-06-2012 10:58 AM

Thank you I will give it a try. I was thinking I could just look in a directory and observe the regular files that have a link count greater than 1. Of course if there are sub directories I would have to do them as well. This won't tell me the location on the file system where the other file names that are hardlinked to the inode number are. For now I just need the hardlink count for a directory anyway. As an administrator I would want to keep track of the hardlinks on the system that is digestable kept in an updateable database. Even if it was a script that displayed ALL matching inode numbers for objects with absolute path.
683358:/harry/a/a1
683358:/harry/a/a2
683358:/harry/b/a3
683358:/harry/b/a4
It would also be nice if the shell was cofigured to display hardlinks like it does with other file types ("-" "d" "l") with path like symlinks.
683358 hrw-r--r-- 4 root root 0 Nov 5 14:11 a4 --> /harry/a/a1
To make it recursive...?
#find -r /your_directory | stat -c "%F %h %N" /your_directory | awk '{if ( ($1 == "regular") && ($2 == "file") && ($3 > 1) ) print $0 }' or

#find -r /your_directory | stat -c "%F %h %N" | awk '{if ( ($1 == "regular") && ($2 == "file") && ($3 > 1) ) print $0 }' or

#stat -c "%F %h %N" /your_directory | find -r /your_directory | awk '{if ( ($1 == "regular") && ($2 == "file") && ($3 > 1) ) print $0 }'
At the end of the string I should be able to add > /harry/hardlinks.txt to save output to file?

GazL 11-06-2012 01:43 PM

Interesting exercise;

Here's one that will work at a filesystem wide level
Code:

#!/bin/bash
#  List inodes in filesystem that have more than one hard link
#
#  Usage:
#    ls-links <directory>
#
#    <directory> will be automatically converted to the TLD of the filesystem
#
#  Output format:
#    <inode> <filename>...


mountpoint="$( stat -c "%m" $1 )"

prev_inode='none'

while read inode filename
do
  if [ "$inode" = "$prev_inode" ]; then
      echo -n " $filename"
  elif [ "$prev_inode" = 'none' ]; then
      echo -en "$inode $filename"
  else
      echo -en "\n$inode $filename"
  fi
  prev_inode="$inode"
done < <( find "$mountpoint" -xdev -type f ! -links 1 -printf "%i %P\n" | sort -k 1n,2)

if [ "$prev_inode" != 'none' ]; then
  echo ""
fi

exit


harrytapp 11-06-2012 04:02 PM

Quote:

Originally Posted by GazL (Post 4823616)
Interesting exercise;

Here's one that will work at a filesystem wide level
Code:

#!/bin/bash
#  List inodes in filesystem that have more than one hard link
#
#  Usage:
#    ls-links <directory>
#
#    <directory> will be automatically converted to the TLD of the filesystem
#
#  Output format:
#    <inode> <filename>...


mountpoint="$( stat -c "%m" $1 )"

prev_inode='none'

while read inode filename
do
  if [ "$inode" = "$prev_inode" ]; then
      echo -n " $filename"
  elif [ "$prev_inode" = 'none' ]; then
      echo -en "$inode $filename"
  else
      echo -en "\n$inode $filename"
  fi
  prev_inode="$inode"
done < <( find "$mountpoint" -xdev -type f ! -links 1 -printf "%i %P\n" | sort -k 1n,2)

if [ "$prev_inode" != 'none' ]; then
  echo ""
fi

exit


Interesting script :-) I suspect that I just copy to a text file and save it as... ".fshdlnks" to keep it visible and make it executable.
I am an old DOS buff that evolved/endured through (draconian) windows and am no stranger to the command line, Just a little rusty :-)
So I decided to take a course on Unix to see where it all started. The instructor does not follow a book and his methodology/terminology leaves a bit to be desired. This is not an actual homework assignment It was at the bottom of a lab he handed out at the begining of the semester. I learn best by getting my hands on and digging in, I just need something to work with. These command lines/scripts are an opportunity to explore, I don't just want to know the answer I am compelled to know how and why. In 1997 my brother gave me an IBM 286 with a 20Mb hard drive and I explored every bit :-) of that system using Help.Hlp/Qbasic. Three months later I was building my own system(AMD K-5 133 with 8Mb ram)a real screamer. I look forward to having fun exploring the Unix file system and the Unix/Linux shell commands.

Would it be simple to just enter a directory do a ls -lia command and then look at all the regular files that have a link count more than one?
Or another way to put it. Is it possible for a regular file to have a link count of "1" and still be hardlinked with another file?
Thanks Harry

GazL 11-06-2012 06:17 PM

Quote:

Originally Posted by harrytapp (Post 4823679)
Or another way to put it. Is it possible for a regular file to have a link count of "1" and still be hardlinked with another file?
Thanks Harry

Nope. A file with a link count of 1 is only linked to a single directory entry.

Rather than think of them as a link pointing to another file, think of them as an additional name for the same file, but where each name is equal to the other (there is no 'original' and 'link'). It should make a little more sense that way.

Hard links are generally considered a bit of a pain to deal with, so most people just stick to using symbolic links instead (which do follow the more intuitive 'original' and 'link' concept).


Hope that helps.

chrism01 11-07-2012 02:00 AM

Quote:

I look forward to having fun exploring the Unix file system and the Unix/Linux shell commands.
These are a good place to start
http://rute.2038bug.com/index.html.gz
http://tldp.org/LDP/Bash-Beginners-G...tml/index.html
http://www.tldp.org/LDP/abs/html/

GlennsPref 11-08-2012 09:45 PM

Hi, sorry for the distraction.

I write very few scripts, but I found this useful.

It's a 4 part tutorial, Tips and Tricks for a (Linux/Unix)New User.

And anything by Jerry Peek (imho), these in particular...Wizard Boot Camp (10 articles)

September 2007: Wizard Boot Camp, Part One
June 2008: Wizard Boot Camp, Part Ten

I'm still learning..

All the best.

GazL 11-09-2012 06:35 AM

Quote:

Originally Posted by GlennsPref (Post 4825468)
I write very few scripts, but I found this useful.

It's a 4 part tutorial, Tips and Tricks for a (Linux/Unix)New User.

When the first example of section 4 gives this (note the spacing on the assignment):
Code:

myvar = "Hello, world"
echo $myvar

... and then goes on to repeat the same error throughout the rest of the article, I'm afraid I can't recommend it.

GlennsPref 11-09-2012 08:35 AM

My Back up is on tape here someplace(?)
 
I can't disagree, I had completely forgotten about that error. Sorry !

I was just starting with zsh, not knowing bash.

I sorted it for my self, the bash error.

I used the distro man and help and info files to get some sort of system worked out.

I have a A4 copy that tute printed out with hand writing on it. (probably still here somewhere)

It taught me a lot.

And the excersizes were interesting.

It's been years since I saw it.

Regards Glenn


All times are GMT -5. The time now is 05:21 PM.