bash script permissions listing - bash

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.

Related

find bash command returns ./ and how do I iterate through each file?

I'm running bash script within Docker container.
All of my files are located in the workspace/app directory.
I cd into /app and use find commands to find directory path for each file.
The problem is when I use pylint, filename returns ./directory_name/file_name.py.
How can I get ... workspace/directory_name/file_name.py?
#!/bin/bash
awd="$(pwd)app"
lint_path="${awd}/.pylintrc"
>>> cd /app
for file in $(find . -name '*.py' -type d); do
filename=$(basename $file)
if [[ $filename != "__init__.py" ]] ; then
echo "$file"
^ prints "./directory__name/file_name.py
How can I get "/app/directory_name/file_name.py"????
fi
done
Give find an absolute path to . with find "$PWD".
Also, use while read instead of for:
while read file; do
...
done < <(find "$PWD" -name '*.py' -type d)

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.

"find" command with a variable directory

I'm trying to list the files in a directory that is given by the variable DIR. My code looks like this so far:
for i in `find $DIR -name "*.txt"
The variable DIR is already defined. I'm not sure what the syntax is here.
ls "${DIR}/*.txt"
or
find "${DIR}" -name "*.txt"
should do the trick. The first one only lists *.txt files in the directory itself, the second one also *.txt files in subdirectories.
I guess you want to execute a given action on all files with extension "txt" under $DIR and/or its subdirs. As usual there are different solutions.
This one:
$ for i in $(find "$DIR" -name \*.txt) ; do echo "Do something with ${i}" ; done
won't work if file path (either the file itself or one subdirectory) contains spaces.
But you can use this:
$ find "$DIR" -type f -name \*.txt | while read i ; do echo "Do something with ${i}" ; done
or this:
$ find "$DIR" -type f -name \*.txt -print0 | xargs -0 -I {} echo "Do something with {}"
or this:
$ find "$DIR" -type f -name \*.txt -exec echo "Do something with {}" \;
or... 100 additional solutions.
Not sure what you want.
find $DIR -name "*.txt" -print
will list all the files that end with .txt and are located in $DIR or its subdirectories. You can omit the -print as that is the default behaviour anyway.
If you have a simple thing you want to do with this file, you can use find's -exec function:
find $DIR -name "*.txt" -exec wc -l {} \;
Or you can use a loop:
for f in `find $DIR -name "*.txt"`; do
wc -l $f
mv $f /some/other/dir/
fi
note: as #mauro helpfully pointed out, this will not work if the DIR or the file names contain spaces.
Cheers

Bulk rename directories with prefix Unix

I am trying to bulk rename directories with a prefix in Unix. Prefix like abc-
So if current directory is 123, I want to make it abc-123, etc
I've tried
for d in $(find . -name '*' -type d) ; do
mv $d $(echo $d | sed 's/$d/abc-$d/g')
done
but that doesn't work. Do very little shell scripting so any help would be appreciated.
rename command is not available
Thank you!
If I understand your question, you could do it with one line and find -exec like so,
find . -type d -depth -execdir mv {} abc-{} \;
Try:
for d in $(find . -depth -type d); do
b=$(basename $d)
p=$(dirname $d)
mv -v $d $p/abc-$b
done
Note that the -depth argument is really important: it ensures that the directories are processed from bottom to top, so that you rename child directories before their parents. If you don't do that then you'll end up trying to rename paths that no longer exist.
Also I recommend replacing line 4 with
echo "mv -v $d $p/abc-$b"
and running that version of the loop first so you can see what it will do before trying it for real.

IF Statement to Delete Symbolic Link

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

Resources