Find symlinks to certain directory or one of its subdirs - linux

Is there an easy way to show whether there are any symlinks in a specified path pointing to a certain directory or one of its children?

A simple and fast approach, assuming that you have the target as absolute path (readlink(1) may help with that matter):
find $PATH -type l -xtype d -lname "$DIR*"
This finds all symlinks (-type l) below $PATH which link to a directory (-xtype d) with a name starting with $DIR.
Another approach, which is O(n*m) and therefore may take ages and two days:
find $DIR -type d | xargs -n1 find $PATH -lname
The first find lists $DIR and all its subdirectories which are then passed (xargs), one at a time (-n1), to a second find which looks for all symlinks originating below $PATH.
To sum things up: find(1) is your friend.

Following up on the answer given by earl:
-xtype does not work on Mac OSX, but can be safely omitted:
find $PATH -type l -lname "$DIR*"
Example:
find ~/ -type l -lname "~/my/sub/folder/*"

Have a look at the findbl (bad links) script in fslint. It might give you some hints:
http://code.google.com/p/fslint/source/browse/trunk/fslint/findbl

Related

recursively find directories without setgid set

In linux, how do you recursively pull up a list of all directories that do NOT have the setgid bit set?
I know you can do
find . -type d /perm g+s
to find all the directories that have it set, but it's not obvious to me how to negate this. Or if another tool is more appropriate for this use case.
I've got a rather large directory tree and I'm trying to limit the operations I do on them.
You can simply add \! before an expression in find in order to negate it.
find . -type d \! -perm -g+s

See if directory rec is used as symlink in Linux

I want to see, if a symlink points to a directories in a specific dir - recursively.
Of course, I clould use
find / -type l -ls 2>/dev/null |grep /targetpath
But I do not want type all the (recurse) paths.
So I put all symlinks on my system into a file once.
find / -type l -ls 2>/dev/null >~/symlinks.txt
Then I list the directories recursively.
find /targetpath to start/ -maxdepth 2 -type d
And that is my question:
Can I pipe these paths from the last command to grep?
Grep should look into my file symlinks.txt and show the linecontent of matching lines (could be more symlinks pointing to this DIR)
I tried something like
find /targetpath to stat/ -maxdepth 2 -type d | xargs -0 -ifoo grep foo symlinks.txt
But it does not do, what I expect.
Or maybe an other, better solution?
From man find:
-lname pattern
File is a symbolic link whose contents match shell pattern pattern. [...]
Try:
find / -lname '*/targetpath/*'
See find-all-symlinks-to-a-directory-and-change-target-to-another-directory.

Using Perl how can I clean up left over directories with no files?

There is a specific directory which is used as a temp/scratch directory by some program.
E.g. /a/b/c/work
Under work multiple hierarchical directories may exist e.g.
/a/b/c/work/
\d1/
\d1.1
\d2
\d2.2
What I want is to clean up this work directory as there are left over files that take space.
Essentially I need to delete all subdirectories under work that the leaf directory is empty.
So if d1.1 is empty but d2.2 has files then delete everything under d1 (including d1) but not d2.
What is the cleanest/standard way to do this in perl?
I thought to use a solution with backticks e.g. rm -rf etc but I thought there could be some better way than coding sequences of ls folowed by rm
Note: Just to be clear. I want a solution in Perl as this is not a one time thing and I dont want to do this manually each time
If you use find command this way you can achieve it.
find /path/to/dir -empty -type d -delete
Where,
-empty Only find empty files and make sure it is a regular file or a directory.
-type d Only match directories.
-delete Delete files.
Always put -delete option at the end of find command as find command line is evaluated as an expression, so putting -delete first will make find try to delete everything below the starting points you specified.
To automate this in shell script follow below code:
path=`pwd`
find $path -empty -type d -delete
or you can give certain input as arguments of shell script like myShell.sh /path/to/mydir in that case the following code will be do the work,
$path=$1
find $path -empty -type d -delete
As for if you really want to go for perl you can find your answer as follows
use strict;
use warnings;
use File::Util;
my $path = '...';
my $fu = File::Util->new();
my #all_dirs = $fu->list_dir($path, '--recurse', '--dirs-only');
my #empty_dirs = grep { not $fu->list_dir($_) } #all_dirs;
also a short method
perl -MFile::Find -e"finddepth(sub{rmdir},'.')"
which is explained very good here.

Find Directories With No Files in Unix/Linux

I have a list of directories
/home
/dir1
/dir2
...
/dir100
Some of them have no files in it. How can I use Unix find to do it?
I tried
find . -name "*" -type d -size 0
Doesn't seem to work.
Does your find have predicate -empty?
You should be able to use find . -type d -empty
If you're a zsh user, you can always do this. If you're not, maybe this will convince you:
echo **/*(/^F)
**/* will expand to every child node of the present working directory and the () is a glob qualifier. / restricts matches to directories, and F restricts matches to non-empty ones. Negating it with ^ gives us all empty directories. See the zshexpn man page for more details.
-empty reports empty leaf dirs.
If you want to find empty trees then have a look at:
http://code.google.com/p/fslint/source/browse/trunk/fslint/finded
Note that script can't be used without the other support scripts,
but you might want to install fslint and use it directly?
You can also use:
find . -type d -links 2
. and .. both count as a link, as do files.
The answer of Pimin Konstantin Kefalou prints folders with only 2 links and other files (d, f, ...).
The easiest way I have found is:
for directory in $(find . -type d); do
if [ -n "$(find $directory -maxdepth 1 -type f)" ]; then echo "$directory"
fi
done
If you have name with spaces use quotes in "$directory".
You can replace . by your reference folder.
I haven't been able to do it with one find instruction.

How to find all files which are basically soft or hard links of other directories or files on linux?

How could I get the list of all linked files on my system or from a certain directory. I used to create links but they became unmanageable with time. I want the list of all such links from a directory. Can anyone help?
Finding symlinks is easy:
% find . -type l
Finding hard links is tricky, because if a subdirectory of the directory in question also has subdirectories then those increase the hard link count. That's how subdirectories are linked to their parents in UNIX (it's the .. entry in each subdirectory).
If you only want to find linked files (and not directories), this will work:
% find . -type f \! -links 1
This works because a file that does have hard links will have a link count > 1, and unlinked file has a link count == 1, hence this command looks for all files whose link count <> 1
Alternatively, on newer versions of find you could use:
% find . -type f -links +1
This works for the same reason as above; however, newer versions of find can take +n or -n instead of just a number. This is equivalent to testing for greater than n or less than n, respectively.
find / -xdev -samefile filename
#OP, If you have GNU find, you can find hard links using -printf "%n",
e.g.
find /path -type f -printf "%f/%n/%i\n" | while IFS="/" read filename num_hlinks inum
do
echo "Filename: $filename. Number of hard links: $num_hlinks, inode: $inum"
# if 2 or more files have the same inode number, then they are hard links.
# you can therefore count how many $inum that are the same and determine those hard links, which
# you have to try doing yourself.
done
See e.g. here
https://www.gnu.org/software/findutils/manual/html_node/find_html/Hard-Links.html
or combine Alnitak and amber_linux answer into
find -L /where/to/search -samefile /some/link/to/file
to find all hard and soft links to a given file.

Resources