IF Statement to Delete Symbolic Link - shell

I am trying to remove an error from appearing on the terminal (it annoys me as it is not one that I need to be worried about).
I have the following code which will check for a broken symbolic link, and if the link is broken it will delete the link:
find /usr/lib/libdb.so -xtype l -delete
How do I change this to a iIF statement?
if [ broken link ] then;
delete file
else
do nothing
fi
Could anyone shed any light on this for me please?

You can use this find:
find /usr/lib/libdb.so -type l -not -exec test -e '{}' \; -print -delete
-not -test -e will detect only broken files(links) and delete them after printing.

To follow your approach, you could try this command:
if [ "`find /usr/lib/libdb.so -type l -xtype l`" != "" ]; then
echo delete file
else
echo do nothing
fi
or, more concisely:
find /usr/lib/libdb.so -type l -xtype l -print -delete

Not tested but give it a try
FILES=`find /usr/lib/libdb.so | grep -v '\.disabled$' | sort`
for F in $FILES; do
if [ -L $F ]; then
if readlink -q $F >/dev/null ; then
delete file
else
DO NOTHING
fi
fi
done

Related

bash if then cp as hardlinks

I would like for the following to hardlink all files to destination, except those directories defined. The find piece is working, but it won't copy any files.
#!/bin/sh
tag_select=$1
source=$3
dest="/backup/"
{
if [[ "$1" = "backup" ]]; then
find . -mindepth 1 -maxdepth 1 ! -name "dir1" ! -name "dir2" | while read line
do
cp -lr "$3" "$dest"
done
fi
}
Please note, I do not want to use rysnc as I would like to create hardlinks in the destination. Thank you in advance!
I guess you know why "$2" doesn't appear anywhere, so we will just presume you are correct. You also understand that every file you find source (e.g. "$3") will be linked to $dest no matter what filenames are discovered by find because you make no use of "$line" that you use as your while read line loop variable. It appears from the question, you want to link all files in source in dest (you must confirm this is your intent) If so, find itself is all you need, e.g.
find source -maxdepth 1 ! -name "dir1" ! -name "dir2" -execdir cp -lr '{}' "$dest" \;
which will find all files (and directories) for 1-level and hardlink each of the files in dest. If that wasn't your intent, please let me know and I'm happy to help further. Your original posts was somewhat an opaque pot of shell stew...
Replace your find command with a simple glob; this also has the benefit of working for any valid file name, not just the ones that don't have newlines in them.
#!/bin/sh
tag_select=$1
source=$3
dest="/backup/"
if [ "$1" = "backup" ]; then
for f in "$source"/*; do
case $f in
dir1|dir2) continue ;;
esac
cp -lr "$f" "$dest"
done
fi
try This
#!/bin/sh
tag_select=$1;
source=$2;
dest="/backup/";
if [ "$1" = "backup" ]; then
find $source -mindepth 1 -maxdepth 1 ! -name "dir1" ! -name "dir2" -exec cp -lr {} "$dest" \;
fi
your command should be
./code.sh backup source_folder_path
example
./code.sh backup ~/Desktop
Try below code for only files in the dir
find $source -maxdepth 1 -type f -exec sh -c "ln -f \"\$(realpath {})\" \"$dest\$(basename {})\"" \;
you cant hard link folders.

Change extension for every file in dir, except *.txt

I have a directory containing lot of files - txt and others.
I want to change extension those others file to txt
For now - i use this:
find . ! -name '*.txt' -type f -exec ls -f {} + > to_txt.txt
for i in ``cat to_txt.txt``; do
mv $i $i.txt && echo $i "File extension have been changed" || echo "Something went wrong"
done;
rm to_txt.txt
Script works fine, but i think it is clumsy
Is there any smarter and elegant way to do this?
Just use the -exec to perform the mv command:
find . ! -name '*.txt' -type f -exec mv {} {}.txt \;
# ^^^^^^^^^^^^
# here the magic
How does this work?
find . ! -name '*.txt' -type f is what you already had: it looks for those files whose name does not end with .txt.
Then, the key is the usage of -exec: there, we make use of {} that carries the value of every file that has been found. Since it acts as a variable, you can use it as so and perform commands. In this case, you want to do mv $file $file.txt, so this is what we do: mv {} {}.txt. To have it work, we finally have to add the \; part.

delete a file present in multiple directories based on the status of find command in unix

I need to delete a file present in multiple directories if it is found else ignore. I tried the following snippet.
ls $dir/"$input.xml" 2> /dev/null
var = `echo$?`
if [[ $var == 0 ]]; then
echo -e "\n Deleting...\n"
rm $dir/"$input.xml"
It failed.
Can anyone suggest me a better solution or modify the above snippet to suit the solution?
Not 100% sure what do you mean with "delete a file present in multiple directories if it is found else ignore". Assuming that you simply want to delete some files that are somewhere under $dir, do this:
Use find to find the files, and pipe to xargs rm:
find "$dir" -type f -name "*.xml" | xargs rm
If your filename is likely to contain spaces then do this:
find "$dir" -type f -name "*.xml" -print0 | xargs -0 rm
To supress the rm error message in case there are no files:
find "$dir" -type f -name "*.xml" -print0 | xargs -0 rm 2>/dev/null
To make your code working Try this [Insert space],
`echo $?`
Instead of this,
`echo$?`

bash script permissions listing

I want to find the permissions (777) for a directory recursively in a bash script. This is only finding directories permissions and not files. Any help appreciated.
#!/bin/bash
x=777
dir=/dir
perms=$(stat -c %a $dir)
if [[ $perms = $x ]]; then
find $dir -type d -perm $x > list
fi
if [[ $perms = $x ]]; then
find $dir -type f -perm $x >> list
fi
Maybe this is actually what you are after?
find . -exec stat {} \+
This command should help: find . -type d -perm 777 (replace . with your starting directory). The -type d part makes sure only directories and not regular files are found.

How can I detect whether a symlink is broken in Bash?

I run find and iterate through the results with [ \( -L $F \) ] to collect certain symbolic links.
I am wondering if there is an easy way to determine if the link is broken (points to a non-existent file) in this scenario.
Here is my code:
FILES=`find /target/ | grep -v '\.disabled$' | sort`
for F in $FILES; do
if [ -L $F ]; then
DO THINGS
fi
done
# test if symlink is broken (by seeing if it links to an existing file)
if [ ! -e "$F" ] ; then
# code if the symlink is broken
fi
This should print out links that are broken:
find /target/dir -type l ! -exec test -e {} \; -print
You can also chain in operations to find command, e.g. deleting the broken link:
find /target/dir -type l ! -exec test -e {} \; -exec rm {} \;
this will work if the symlink was pointing to a file or a directory, but now is broken
if [[ -L "$strFile" ]] && [[ ! -a "$strFile" ]];then
echo "'$strFile' is a broken symlink";
fi
This finds all files of type "link", which also resolves to a type "link". ie. a broken symlink
find /target -type l -xtype l
If you don't mind traversing non-broken dir symlinks, to find all orphaned links:
$ find -L /target -type l | while read -r file; do echo $file is orphaned; done
To find all files that are not orphaned links:
$ find -L /target ! -type l
What's wrong with:
file $f | grep 'broken symbolic link'
If it does qualify as a symbolic link, but is „not existing“, its a broken link.
if [[ -h $link && ! -e $link ]] ; then
_info "$link is a BROKEN SYMLINK"
fi
REFERENCE

Resources