I'm trying to compile a very simple bash script that will do the following actions (the script I have so far doesn't seem to function at all so I won't waste time putting this up for you to look at)
I need it to find files by their names. I need the script to take the user input and search the .waste directory for a match, should the folder be empty i'd need to echo out "No match was found because the folder is empty!", and just normally failing to find a match a simple "No match found."
I have defined: target=/home/user/bin/.waste
You can use the built in find command to do this
find /path/to/your/.waste -name 'filename.*' -print
Alternatively, you can set this as a function in your .bash_profile
searchwaste() {
find /path/to/your/.waste -name "$1" -print
}
Note that there are quotes around the $1. This will allow you to do file globbing.
searchwaste "*.txt"
The above command would search your .waste directory for any .txt files
Here you go, pretty straightforward script:
#!/usr/bin/env bash
target=/home/user/bin/.waste
if [ ! "$(ls -A $target)" ]; then
echo -e "Directory $target is empty"
exit 0
fi
found=0
while read line; do
found=$[found+1]
echo -e "Found: $line"
done < <(find "$target" -iname "*$1*" )
if [[ "$found" == "0" ]]; then
echo -e "No match for '$1'"
else
echo -e "Total: $found elements"
fi
Btw. in *nix world there are not folders, but there are directories :)
This is a solution.
#!/bin/bash
target="/home/user/bin/.waste"
read name
output=$( find "$target" -name "$name" 2> /dev/null )
if [[ -n "$output" ]]; then
echo "$output"
else
echo "No match found"
fi
Related
I'm trying to write a bash script to search for files. If the file is found the script should copy it. Otherwise the script should print a message to notify me that it wasn't found.
#!/bin/bash
result=/home/images/newfolder/
while read -r $FILE
do
FOUND="($find $(pwd) -name "$FILE"* -type f print -quit)"
if [ "x$FOUND" != "x" ]
then
echo "copying file: $FOUND"
cp "$FOUND" $result
else
echo "NOT FOUND: $FILE"
fi
done </root/filelist.txt
FOUND 11234567890.jpeg
NOT FOUND 1890.jpeg
FOUND 183290.jpeg
This is a working script. assuming that you have a /tmp/filelist.txt containing what you looking for and files are going to be copied to /tmp. fill free to edit and use.
#!/bin/bash
result=/tmp
while read -r FILE
do
FOUND=$(find $(pwd) -name "$FILE" -type f)
if [ -z "$FOUND" ]; then
echo "NOT FOUND: $FILE"
else
echo "copying file: $FILE"
cp $FILE $result
fi
done < /tmp/filelist.txt
I would like to make a bash function that lists all the directories (and files) inside a given directory.
searchInRepo(){
file_list=`ls $1`
#echo $file_list
for aFile in $file_list; do
echo "$aFile --"
# case : directory
if [ -d $aFile ]
then
echo "$aFile ***"
cd $aFile
searchInRepo $aFile
cd ..
# case : file
elif [ -f $aFile ]
then
echo "$aFile is a regular file"
fi
done
}
As you see, this is a recursive function. When I call it with ls $1 (listing parameter's files) it doesn't recognize the directories as being directories. When I just use ls(no argument involved) everything works fine.
Any suggestions here ?
Cheers !
Why use ls when bash can do it for you? This will check to make sure the argument has a trailing /* so it will work with bare directory names.
if [[ ! "$1" =~ /\*$ ]]
then
if [[ ! "$1" =~ /$ ]]
then
searchpath="$1/*"
else
searchpath="$1*"
fi
fi
echo "Searching $searchpath"
for f in $searchpath; do
if [ -d "$f" ]
then
echo "Directory -> $f"
else
echo "File -> $f"
fi
done
Why even use for loop, find is made for this.
find . # List all files and directories recursively
find . -type f # List only files
find . -maxdepth 1 # List all files and directories in current directory
If you are using git, you can also use git ls-files
I am trying to find if a file exist in an iPhone application directory
Unfortunately, apps directory differs from a device to another
On my device, i use the following command to see if the file exists:
if [[ -f "/var/mobile/Applications/D0D2B991-3CDA-457B-9187-1F02A84FF3AB/AppName.app/filename.txt" ]]; then
echo "The File Exists";
else
echo "The File Does Not Exist";
fi
I want a command that would automatically search if the file exist without the need to specify the "variable" name inside the path.
I tried this:
if [[ -f "/var/mobile/Applications/*/AppName.app/filename.txt" ]]; then
echo "The File Exists";
else
echo "The File Does Not Exist";
fi
But no luck, it didn't find the file,
Maybe because i have 2 path of /var/mobile/Applications/*/AppName.app/ since i have cloned the app.
I would like to get a way to be able to find if the file filename.txt exists inside any folder named AppName.app inside this directory /var/mobile/Applications/*/
You can do this as follows:
[[ $(find /var/mobile/Applications/*/AppName.app/ -name filename.txt -print -quit | wc -l) -gt 0 ]] && echo "The File Exists" || echo "The File Does Not Exist"
The -f test can only take one argument. You would need to put it in a loop to check if some glob exists and its matches some regular file, i.e.
shopt -s nullglob
found=
for file in /var/mobile/Applications/*/AppName.app/filename.txt; do
[[ -f $file ]] && found=: && break
done
[[ -n $found ]] && echo "The File Exists" || echo "The File Does Not Exist"
If you're not sure specifically where the file is located you can use find, doing something like below which will exit early if found. (should work for gnu find, haven't tested on bsd)
if [[ -f $(find /some_root_directory -type f -name 'filename.txt' -print -quit) ]]; then
echo "The File Exists"
else
echo "The File Does Not Exist"
fi
# if a glob matches nothing, remove it instead of leaving the literal glob
shopt -s nullglob
# stick all matches in an array
files=( /var/mobile/Applications/*/AppName.app/filename.txt )
case "${#files[#]}" in
0 ) echo "Sorry, no such file." ;;
1 ) echo "The file exists: ${files[0]}" ;;
* ) echo "There are multiple files matching this pattern: ${files[*]}" ;;
esac
I like this technique for the purpose:
if find /var/mobile/Applications/*/AppName.app/ -name filename.txt -print -quit | grep -q .; then
echo "The File Exists"
else
echo "The File Does Not Exist"
fi
This has some advantages over this form:
[[ $(find ..... -print -quit | wc -l) -gt 0 ]]
Because:
It doesn't need a $() subshell
It doesn't need to count lines with wc
It doesn't need to compare numbers with the -gt operator
It doesn't need to be inside a [[ ... ]]
Basically it's a find ... | grep -q . versus [[ $(find ... | wc -l) -gt 0 ]]
Or find ... | grep -q . versus [[ -f $(find ...) ]]
How can I use the test command for an arbitrary number of files, passed in using an argument with a wildcard?
For example:
test -f /var/log/apache2/access.log.* && echo "exists one or more files"
Currently, it prints
error: bash: test: too many arguments
This solution seems to me more intuitive:
if [ `ls -1 /var/log/apache2/access.log.* 2>/dev/null | wc -l ` -gt 0 ];
then
echo "ok"
else
echo "ko"
fi
To avoid "too many arguments error", you need xargs. Unfortunately, test -f doesn't support multiple files. The following one-liner should work:
for i in /var/log/apache2/access.log.*; do test -f "$i" && echo "exists one or more files" && break; done
By the way, /var/log/apache2/access.log.* is called shell-globbing, not regexp. Please see Confusion with shell-globbing wildcards and Regex for more information.
First, store files in the directory as an array:
logfiles=(/var/log/apache2/access.log.*)
Then perform a test on the count of the array:
if [[ ${#logfiles[#]} -gt 0 ]]; then
echo 'At least one file found'
fi
This one is suitable for use with the Unofficial Bash Strict Mode, no has non-zero exit status when no files are found.
The array logfiles=(/var/log/apache2/access.log.*) will always contain at least the unexpanded glob, so one can simply test for existence of the first element:
logfiles=(/var/log/apache2/access.log.*)
if [[ -f ${logfiles[0]} ]]
then
echo 'At least one file found'
else
echo 'No file found'
fi
If you wanted a list of files to process as a batch, as opposed to doing a separate action for each file, you could use find, store the results in a variable, and then check if the variable was not empty. For example, I use the following to compile all the .java files in a source directory.
SRC=`find src -name "*.java"`
if [ ! -z $SRC ]; then
javac -classpath $CLASSPATH -d obj $SRC
# stop if compilation fails
if [ $? != 0 ]; then exit; fi
fi
You just need to test if ls has something to list:
ls /var/log/apache2/access.log.* >/dev/null 2>&1 && echo "exists one or more files"
Variation on a theme:
if ls /var/log/apache2/access.log.* >/dev/null 2>&1
then
echo 'At least one file found'
else
echo 'No file found'
fi
ls -1 /var/log/apache2/access.log.* | grep . && echo "One or more files exist."
Or using find
if [ $(find /var/log/apache2/ -type f -name "access.log.*" | wc -l) -gt 0 ]; then
echo "ok"
else
echo "ko"
fi
This condition below doesn't produce stderr. the condition's blackhole (/dev/null) doesn't prevent the stderr in cmd.
if [[ $(ls -1 /var/log/apache2/access.log.* | wc -l ) -gt 0 ]] 2> /dev/null
therefore I suggests this code.
if [[ $(ls -1 /var/log/apache2/access.log.* | wc -l ) -gt 0 ]] 2> /dev/null
then
echo "exists one or more files."
fi
more simplyfied:
if ls /var/log/apache2/access.log.* 2>/dev/null 1>&2; then
echo "ok"
else
echo "ko"
fi
I'm using the find command in my bash script like so
for x in `find ${1} .....`;
do
...
done
However, how do I handle the case where the input to my script is a file/directory that does not exist? (ie I want to print a message out when that happens)
I've tried to use -d and -f, but the case I am having trouble with is when ${1} is "." or ".."
When the input is something that doesn't exist it does not enter my for loop.
Thanks!
Bash gives you this out of the box:
if [ ! -f ${1} ];
then
echo "File/Directory does not exist!"
else
# execute your find...
fi
Bash scripting is a bit weird. Practice before implementation. But this site seems to break it down well.
If the file exists, this works:
if [ -e "${1}" ]
then
echo "${1} file exists."
fi
If the file does not exist, this works. Note the '!' to denote 'not':
if [ ! -e "${1}" ]
then
echo "${1} file doesn't exist."
fi
assign the find to a variable and test against the variable.
files=`find ${1} .....`
if [[ "$files" != “file or directory does not exist” ]]; then
...
fi
You can try something like this:
y=`find . -name "${1}"`
if [ "$y" != "" ]; then
for x in $y; do
echo "found $x"
done
else
echo "No files/directories found!"
fi