How can I trap a return of two variables with an if statement using bash? - macos

My task is to list a user's folder in /Users on a mac. I have to allow for dupe folders (large enterprise of 650 mac clients) or where a desktop analyst has backed up a folder and appended something. My $fourFour variable picks that up. However, I must flag that for logging.
This is where I have got below. The variable $fourFour may return one or more folders and I need to get the if statement to echo this accordingly.
folders=$(ls -d */ | grep $fourFour | awk '{print $(NF)}' | sed 's/\///')
echo folders is $folders
if [[ "$folders" == "" ]]; then
echo no items
else
echo one or more items
fi

Do not parse the output of ls unless you absolutely have to. Your code above has major issues with whitespace in folder names.
Bash arrays can be your friend:
#!/bin/bash
shopt -s nullglob
folders=(*$fourFour*/)
# Remove the trailing slashes
folders=("${folders[#]%/}")
if [[ "${#folders[#]}" -gt 0 ]]; then
echo "Folders:" "${folders[#]}"
else
echo "No folders"
fi

you don't have to call so many tools to find your folders. Just use the shell (bash)
#!/bin/bash
shopt -s nullglob
for dir in *$fourFour*/ # putting a slash "/" ensures you get directory entries
do
echo "Do something with $dir"
# if you want to check if its empty folder
v=$(echo "$dir"/*)
case "${#v}" in
0) echo "No files in $dir";;
*) echo "Files in $dir";;
esac
done
if you just want to check whether there are any folders that matched your pattern
v=$(echo "$four"/)
case "${#v}" in
0) echo "0 item";;
*) echo "1 or more item";;
esac

Related

Bash what other type exists other than -f and -d in bash?

I am trying to loop around a file and directories inside a bash script. I see that my code hits the else condition which is neither directory nor file. What file is it? How do I check that? Next, why is it going to else condition I am unsure. Basically, my goal is to copy the files and directories from the source to the destination. Here is the source code. I am running this inside the vscode git bash - windows.
Also, I had to do item=$(echo $item | sed 's/[=:]//g') this since I was getting trailing in vscode git bash. I am unsure why do I get trailing ':'.
for item in $(ls src/$pre-com/* 2>/dev/null); do
if [[ -f $item ]]; then
echo "$item"
cp $item src/com1/
elif [[ -d $item ]]; then
echo "doing directory copy"
item=$(echo $item | sed 's/[=:]//g')
echo $item
cp -vrf $item src/com1/
else
echo "Unknown type"
fi
done

bash script with if [[ ! -f path_to_files ]]

On MacOS Catalina, I have a bash script with
if [[ ! -f $CR/home/files/Recovery_*.txt ]]
then
echo "File does not exists in /home/files directory. Exiting" >> $log
echo "Aborted - $CR/home/files/Recovery_*txt not exist"
exit
fi
Even though there are 2 files in the directory the script exits. If I list directory contents beforehand there are 2 files. If I change it as follows the if is skipped:
if [[ `ls -la $CR/home/files/Recovery_*.txt | wc -l` -eq 0 ]]
then
echo "No files are :"
exit
fi
I am wanting to use the if -f conditional.
Any suggestions please?
Cheers, C
If you use nullglob, a glob expression that doesn't match returns an empty string. This lets us count files in bash without spawning other processes. Create an array with the expression, then check its length.
shopt -s nullglob
files=($CR/home/files/Recovery_*.txt)
if [[ ${#files[#]} -eq 0 ]]
then
echo "No files"
exit
fi
[Edited]
The error was not the variables, but the missing shebang as the script has come across from W2K3 SFU.
The tip about shellchecker.net was awesome and I will use that from now.
Thanks.

Checking the input arguments to script to be empty failed in bash script

This a small bash program that is tasked with looking through a directory and counting how many files are in the directory. It's to ignore other directories and only count the files.
Below is my bash code, which seems to fail to count the files specifically in the directory, I say this because if I remove the if statement and just increment the counter the for loop continues to iterate and prints 4 in the counter (this is including directories though). With the if statement it prints this to the console.
folder1 has files
Looking at other questions I think the expression in my if statement is right and I am getting no compilation errors for syntax or another problems.
So I just simply dumbfounded as to why it is not counting the files.
#!/bin/bash
folder=$1
if [ $1 = empty ]; then
folder=empty
counter=0
echo $folder has $counter files
exit
fi
for d in $(ls $folder); do
if [[ -f $d ]]; then
let 'counter++'
fi
done
echo $folder has $counter files
Thank you.
Your entire script could be very well simplified as below with enhancements made. Never use output of ls programmatically. It should be used only in the command-line. The -z construct allows to you assert if the parameter following it is empty or non-empty.
For looping over files, use the default glob expansion provided by the shell. Note the && is a short-hand to do a action when the left-side of the operand returned a true condition, in a way short-hand equivalent of if <condition>; then do <action>; fi
#!/usr/bin/env bash
[ -z "$1" ] && { printf 'invalid argument passed\n' >&2 ; exit 1 ; }
shopt -s nullglob
for file in "$1"/*; do
[ -f "$file" ] && ((count++))
done
printf 'folder %s had %d files\n' "$1" "$count"

Bash: Find any subdirectories without a given file present

I want to know if my file exists in any of the sub directories below. The sub directories are created in the steps above in my shell script, the below code always tells me the file do not exist (even if it does) and I want the path to be printed as well.
#!/bin/bash
....
if ! [[ -e [ **/**/somefile.txt && -s **/**/somefile.txt ]]; then
echo "===> Warn: somefile.txt was not created in the following path: "
# I want to be able to print the path in which file is not generated
exit 1
fi
I know the file name is somefile.txt which is to be created in all sub-directories, but the subdirectory names change a lot.. Hence globbing.
#!/bin/bash
shopt -s extglob ## enable **, which by default has no special behavior
for d in **/; do
if ! [[ -s "$d/somefile.txt" ]]; then
echo "===> WARN: somefile.txt was not created (or is empty) in $d" >&2
exit 1
fi
done

How to identify files which are not in list using bash?

Unfortunately my knowledge in bash not so well and I have very non-standard task.
I have a file with the files list.
Example: /tmp/my/file1.txt /tmp/my/file2.txt
How can I write a script which can check that files from folder /tmp/my exist and to have two types messages after script is done.
1 - Files exist and show files:
/tmp/my/file1.txt
/tmp/my/file2.txt
2 - The folder /tmp/my including files and folders which are not in your list. The files and folders:
/tmp/my/test
/tmp/my/1.txt
You speak of files and folders, which seems unclear.
Anyways, I wanted to try it with arrays, so here we go :
unset valid_paths; declare -a valid_paths
unset invalid_paths; declare -a invalid_paths
while read -r line
do
if [ -e "$line" ]
then
valid_paths=("${valid_paths[#]}" "$line")
else
invalid_paths=("${invalid_paths[#]}" "$line")
fi
done < files.txt
echo "VALID PATHS:"; echo "${valid_paths[#]}"
echo "INVALID PATHS:"; echo "${invalid_paths[#]}"
You can check for the files' existence (assuming a list of files, one filename per line) and print the existing ones with a prefix using this
# Part 1 - check list contents for files
while read thefile; do
if [[ -n "$thefile" ]] && [[ -f "/tmp/my/$thefile" ]]; then
echo "Y: $thefile"
else
echo "N: $thefile"
fi
done < filelist.txt | sort
# Part 2 - check existing files against list
for filepath in /tmp/my/* ; do
filename="$(basename "$filepath")"
grep "$filename" filelist.txt -q || echo "U: $filename"
done
The files that exist are prefixed here with Y:, all others are prefixed with N:
In the second section, files in the tmp directory that are not in the file list are labelled with U: (unaccounted for/unexpected)
You can swap the -f test which checks that a path exists and is a regular file for -d (exists and is a directory) or -e (exists)
See
man test
for more options.

Resources