Delete file with given extension - bash

I want to remove files with extension that was given by a user. My problem is that it print "Not Found" and "rm: cannot remove ‘*.txt’"
echo Extension?
read ext
if [ -e *$ext ]
then
rm *$ext
else
echo Not Found
fi

Try using the -z flag to check if the $ext variable is empty. The -e flag checks if a file exists.
#!/bin/bash
echo Extension?
read ext
if [ ! -z $ext ]
then
rm *.$ext
else
echo Not Found
fi
I also added a . to the rm command. This reflects the desire to remove by extension. Otherwise, you'd be removing any file that ended with the user input (i.e. program.c and a file named zodiac would both be deleted).

Use a bash array to ensure that white space is handled correctly.
#!/bin/bash
# ask for ext until user enters one
ext=''
while [[ -z $ext ]]; do
read -p 'Extension? ' ext
done
# find files
files=(*"$ext")
if [[ -e ${files[0]} )); then
# delete files (-- prevents injection)
rm -- "${files[#]}"
else
# no files to delete
echo "No files with extension: $ext"
fi

Related

I am trying to find a file in a directory, but the shell code snippet is not detecting it

I have a shell script, which has a code block to find a file in the directory but it is not doing the job. I have a file in my directory "changeip.data", in one of the block i am tring to find the file, but it is not detecting the file. I want to check with the condition that the filename starts with "change".
cd /home/raymond
file = "changeip.data"
if [[ "$file" == change* ]]; then
echo "File found..."
else
echo "File not found..."
fi
Can somebody help me with this?
the problem in your code is extra space. make sure there is no space while pointing to file name. refer the following initilization:
file="changeip.data"
EDIT:
#==================
Full code:
#==================
file="changeip.data"
if [[ "$file" == change* ]]; then
echo "File found..."
else
echo "File not found..."
fi
The issue is that to check is a file exists, you need to use -e but this will only work with complete file names without globbing.
As an alternative, you could try the following:
if [[ "$(find -maxdepth 1 -name "zipp*pm2" | wc -l)" -gt "0" ]];
then
echo "File Found";
else
echo "File Not Found";
fi
This will count the output from the find command and if it is greater than 0, will return "File Found", otherwise "File Not Found"

Bash Recursive Loop searching for file

Our assignment was just a conditional statement to say if a file exists or doesn't in the current directory. I already completed the primary objective but I am just trying to figure out how I could recurse using a loop and finding any other occurrences of the file name.
Currently, I am getting an infinite loop after finding the file in the first directory.
File exists and is located at /home/charlie/file.txt
File exists and is located at /home/charlie/file.txt
...
**Questions:
Would I need to have a nested for loop somewhere even though I am recursively calling the function?
Does using $pwd mess it up as I am trying to step into the directories?
Why is it printing twice as of now?**
#!/bin/bash
if [[ $# -eq 0 ]] ; then
echo 'Usage: findFile_new.sh [file name]'
exit 0
fi
exist="File exists and is located at "
function check() {
for file in $(pwd)/*
do
if [ -d "$file" ]; then
check $file $1
else
## Look for file
if [ -f "$1" ]; then
echo $exist$(pwd)/$1
fi
fi
done
}
check $1
Getting closer....
Why am i getting this as my output????
File exists and is located at
/home/charlie//#/*testFile.txt
File exists and is located at
/home/charlie//compareQuiz.sh/testFile.txt
File exists and is located at
/home/charlie//dir1/dir2/dir3/dir4//*testFile.txt
File exists and is located at
/home/charlie//dir1/dir2/file.txt/*testFile.txt
File exists and is located at
/home/charlie//dir1/dir2/testFile.txt/*testFile.txt
File exists and is located at
/home/charlie//findFile_new.sh/*testFile.txt
File exists and is located at
/home/charlie//testFile.txt/*testFile.txt
File exists and is located at
/home/charlie//testscript.sh/*testFile.txt
File exists and is located at
/home/charlie//~/*testFile.txt
#!/bin/bash
if [[ $# -eq 0 ]] ; then
echo 'Usage: findFile_new.sh [file name]'
exit 0
fi
exist="File exists and is located at "
echo $1 $2
function check() {
for file in $1/*
do
if [ -d "$file" ]; then
check $file $2
else
## Look for file
if [ -f "$2" ]; then
echo $exist$file
fi
fi
done
}
check $1 $2
Yes, you are almost there. A possible problem is the variable $file
will contain pathname to the file such as path/to/the/testFile.txt while
the variable $2 may contain only testFile.txt.
Would you please try the following:
#!/bin/bash
# usage: check path targetname
check() {
local file
for file in "$1"/*; do
if [[ -d $file ]]; then
check "$file" "$2"
elif [[ -f $file && ${file##*/} = $2 ]]; then
echo "found: $file"
fi
done
}
if (( $# != 2 )); then
echo "usage: $0 path name"
exit 0
fi
check "$1" "$2"
The expression ${file##*/} removes the pathname preceding the rightmost slash
inclusive and now you can compare it with $2.
Your search is not truly recursive and will eventually fall into an infinite loop.
Rolling your own Bash script that would cover every case for recursive search within a directory - can be tricky (permission handling and links come to mind...)
What you could do - is to use find which takes care of all recursive woes, and then extract the data you may need. The script (or single command really) would be find . -iname $1
find . (in this directory) -iname match this name and ignore case and $1 first arg value.
From the above you could grep to extract any data you may need.
I know this does not answer your question 1:1, but if you're just starting with Bash, I'd say you're better off using tools provided within Bash first, then trying rolling your own.
As your task was already accomplished and it's more of a general question, I figured I'd provide you with "what I would do". :)
Another point - when using $pwd - this being a bash reserved environment variable, it's better to use $PWD. It makes it simple to understand which env_vars are user declared and which are system reserved.
edit:
If you'd like to see a nice example of how this can be done, please checkout https://www.shellscript.sh/eg/directories/#traverse2.sh

Bash Scripting: I currently am supposed to have 500 files inside a directory, how can I stop a bash script if any files are missing?

I currently have a directory that is supposed to have 500 files. Each file is of the name form List.1.rds, ... List.500.rds. The way I can see which ones are missing is by the following code in bash:
for((i=1; i<=500; i++)); do name="List.${i}.rds"; [[ ! -e "$name" ]] && echo "missing $name"; done
If a file is missing, it returns the missing file name. However, I would like to go one step further and stop the entire script should any file be missing. Is there a way to do this? thanks.
It can be as simple as setting a flag when a file is missing:
miss=0
for ((i=1;i<=500;i++)); do
file=List.$i.rds
if [[ ! -e $file ]]; then
echo "Missing $file"
miss=1
fi
done
# exit if "miss" flag is 1
((miss)) && exit 1

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

Space in directory name crashing .sh - use "usebackq"?

dir1='/d/Dropbox/PhD/Experimental Design/APS/Processed_and_Graphed/InvariantQ'
echo $dir1
for f in A*.xlsx
do
str2=${f%?????}
if [[ ! -d $dir1/$str2 ]]; then
mkdir $dir1/$str2
else
echo "Directory" $dir1/$str2 "already exists, directory not created"
fi
if [[ ! -f $dir1/$str2/$f ]]; then
mv -v $f $dir1/$str2
else
echo "File" $dir1/$str2/$f "already exists, file not copied"
fi
done
I'm trying to get the following script to run, however when it attempts to mkdir $dir1/$str2, it creates:
/d/Dropbox/PhD/Experimental
and returns back the error:
create directory '/d/Dropbox/PhD/Experimental': file exists
create directory 'Design/APS/Processed_and_Graphed/InvariantQ': no such file or directory
I've tried coding the directory name with double quotations, or a '\' in front of the space in 'Experimental Design', but neither method seems to work... It seems this can be achieved in batch files using "usebackq" -is there a way to do this in GitBash for windows? If so, where in my code would it be applied?
Also, is anyone aware as to why testing a statement here using "[[" works, whereas a single "[" doesn't?
Quote your variables to prevent word splitting on the expansion.
dir1='/d/Dropbox/PhD/Experimental Design/APS/Processed_and_Graphed/InvariantQ'
echo "$dir1"
for f in A*.xlsx
do
str2=${f%?????}
if [[ ! -d $dir1/$str2 ]]; then
mkdir "$dir1/$str2"
else
echo "Directory $dir1/$str2 already exists, directory not created"
fi
if [[ ! -f $dir1/$str2/$f ]]; then
mv -v "$f" "$dir1/$str2"
else
echo "File $dir1/$str2/$f already exists, file not copied"
fi
done
It works with [[ because this is shell syntax, not an ordinary command. It recognizes variables specially and doesn't do work splitting on them. This is the same reason that it allows you to use operators like < without quoting them.

Resources