How to negate/ "reverse mean" this search - that is "!" the meaning - shell

if [[ -n $(find $path -name "$string*") ]]
then
<stuff>
else
<stuff>
fi
I want to reverse the above search like
if [[ ! -n $(find $path -name "$string*") ]]
then
<stuff>
else
<stuff>
fi
But it wont allow this because here I am checking the find commands output
any clue.thanks for help

You can reverse the search in find itself using:
find "$path" ! -name "$string*"
btw this is also valid:
[[ ! -n $(find $path -name "$string*") ]]
Or else you can use -z:
[[ -z $(find $path -name "$string*") ]]

Related

if then else twice and if not found then run a command

I have this code:
if [[ $(find /path/to/folder1 -type f -not -path "*configs*" -size -800k 2>/dev/null) ]]; then
echo "[[Warning]]: The files size is under 800 Kilobytes"
if [[ $(find /path/to/another/folder -type f \( ! -iname "123.file*" \) -not -path "*logs*" -size -40k 2>/dev/null) ]]; then
echo "[[Warning]]: The file size is under 40 Kilobytes"
fi
else
Run a command here
fi
The target is:
Get an echo if a file under size found in any of the above paths or get both echo if a file under size found on both paths and run the command at the end only if not files under size found at any of the above two paths.
Both checks are tested and working but it seems that I have the if or else statements in wrong order?
That should work what you have. An easier way would be to use OR (||) in structure below. If both of those statements are false, then you run command.
if statementA || statementB then...
else ...
Your else is already executed when the first if gets false. You could do a
if [[ $(find ....) ]] || [[ $(find ....) ]]; then
else
run
fi
or
if [[ -n $(find ....) || -n $(find ....) ]]; then
else
run
fi
but this would only take care about the running command; you want, however, also display an individual message if the find commands succeed.
There are several possibilities. The easiest would be IMO to use a control variable:
run_command=1
if [[ $(find ....) ]]; then
echo ....
run_command=0
fi
if [[ $(find ....) ]]; then
echo ....
run_command=0
fi
if ((run_command == 1)); then
run ...
fi

Bash Find Function Ubuntu - Find in directory tree, files that have the same name as their directory

I want to find and print files in directory tree, that have the sname name as theirs dirs.
This is my code so far:
#!bin/bash
if [ $# -eq 0 ]
then
echo "No args"
fi
if [[ -d $1 ]] #if its dir
then
find $1 -type f | (while read var1 #for every regular file in dir tree
do
if [[ -f $var1 ]]
then
echo $var1 #full path
# I dont know how to get the dir name
echo $(basename $var1) #file name
echo
#then compare it and print full path
fi
done)
fi
I want to do this using FIND function in bash linux. Thanks
You can use this script with find:
while IFS= read -rd '' f; do
d="${f%/*}"
[[ ${d##*/} == ${f##*/} ]] && echo "$f"
done < <(find . -type f -print0)

Nesting a for loop in an if else statement

if [ ! -f ./* ]; then
for files in $(find . -maxdepth 1 -type f); do
echo $files
else
echo Nothing here
fi
Returns
syntax error near unexpected token `else'
New to this. Can anyone point me to what I did wrong?
You forgot done!
if [ ! -f ./* ]; then
for files in $(find . -maxdepth 1 -type f); do
echo $files
done
else
echo Nothing here
fi
The reason you get a syntax error is because you are not ending the loop with the "done" statement. You should be using a while loop, instead of a for loop in this case, as the for loop will break if any of the filenames contain spaces or newlines.
Also, the test command you have issued will also give a syntax error if the glob expands to multiple files.
$ [ ! -f ./* ]
bash: [: too many arguments
Here is a better way to check if the directory contains any files:
files=(./*) # populate an array with file or directory names
hasfile=false
for file in "${files[#]}"; do
if [[ -f $file ]]; then
hasfile=true
break
fi
done
if $hasfile; then
while read -r file; do
echo "$file"
done < <(find . -maxdepth 1 -type f)
fi
Also, you could simply replace the while loop with find -print if you have GNU find:
if $hasfile; then
find . -maxdepth 1 -type f -print
fi
The syntax for "for" is
for: for NAME [in WORDS ... ;] do COMMANDS; done
You are missing the "done"
Try
if [ ! -f ./* ]; then
for files in $(find . -maxdepth 1 -type f); do
echo $files
done
else
echo Nothing here
fi
BTW, did you mean echo with lowercase rather than ECHO?

How to tell if the output of the "find" command is empty?

I want to return an exit status of 0 if the output is empty and 1 otherwise:
find /this/is/a/path/ -name core.*
When you say you want it to return a particular number, are you referring to the exit status? If so:
[[ -z `find /this/is/a/path/ -name core.*` ]]
And since you only care about a yes/no response, you may want to change your find to this:
[[ -z `find /this/is/a/path/ -name core.* -print -quit` ]]
which will stop after the first core file found. Without that, if the root directory is large, the find could take a while.
Here's my version. :)
[ -z "$(find /this/is/a/path/ -name 'core.*')" ] && true
Edited for brevity:
[ -z "$(find /this/is/a/path/ -name 'core.*')" ]
There are probably many variants, but this is one:
test $(find /this/is/a/path/ -name core.* | wc -c) -eq 0
Perhaps this
find /this/is/a/path/ -name 'core.*' | read
I am using this:
if test $(find $path -name value | wc -c) -eq 0
then
echo "has no value"
exit
else
echo "perfect !!!"
fi

loop over directories to echo its content

The directories are variables set to the full-path
for e in "$DIR_0" "$DIR_1" "$DIR_2"
do
for i in $e/*
do
echo $i
done
The output for each line is the full path. I want only the name of each file
You are looking for basename.
This is the Bash equivalent of basename:
echo "${i##*/}"
It strips off everything before and including the last slash.
If you truly do not wish to recurse you can achieve that more succinctly with this find command:
find "$DIR_0" "$DIR_1" "$DIR_2" -type f -maxdepth 1 -exec basename{} \;
If you wish to recurse over subdirs simply leave out maxdepth:
find "$DIR_0" "$DIR_1" "$DIR_2" -type f -exec basename{} \;
to traveling a directory recursively with bash
try this you can find it here
#! /bin/bash
indent_print()
{
for((i=0; i < $1; i++)); do
echo -ne "\t"
done
echo "$2"
}
walk_tree()
{
local oldifs bn lev pr pmat
if [[ $# -lt 3 ]]; then
if [[ $# -lt 2 ]]; then
pmat=".*"
else
pmat="$2"
fi
walk_tree "$1" "$pmat" 0
return
fi
lev=$3
[ -d "$1" ] || return
oldifs=$IFS
IFS=""
for el in $1/ *; do
bn=$(basename "$el")
if [[ -d "$el" ]]; then
indent_print $lev "$bn/"
pr=$( walk_tree "$el" "$2" $(( lev + 1)) )
echo "$pr"
else
if [[ "$bn" =~ $2 ]]; then
indent_print $lev "$bn"
fi
fi
done
IFS=$oldifs
}
walk_tree "$1" "\.sh$"
See also the POSIX compliant Bash functions to replace basename & dirname here:
http://cfaj.freeshell.org/src/scripts/

Resources