Reputation: 751
I am having a directory.This directory has a lot of subdirectories which contain html pages and some c source code files,Makefiles etc etc.The script I am trying to write would be executed from one directory which has all these subdirectories. Following is the set of directories and files you can see
ls
delete.sh lddbus Makefile misc-progs sbull scullc scullp short simple snull usb
include LICENSE misc-modules pci scull sculld scullv shortprint skull tty
Some of them are directories and some are files in the subdirectories above there are further subdirectories and html pages also which I want to eliminate. The manual way would be do go to each directory and remove the pages via following command
rm *.html*
Since the html page has name ending with ?=/something
sort of names.
So I decided to write a shell script.
But what I am not clear is how will I take directory names as arguments in my shell script.If I decided to use a for loop or some thing similar.
In this case what should I be doing?
I do not want to use
find . -name '*.html*' -exec rm -f {} \;
As I am doing this for learning purpose.
Upvotes: 1
Views: 7773
Reputation: 20591
This code snippet will run ls
for every subdirectory in current dir:
for d in * .[!.]* ..?*; do
test -d "${d}" && ls "${d}"
done
You can adapt it to run a command, for each subdirectory, that you like.
If you want to get deeper in the directory hierarchy, you can wrap this code in a function and rerun it for every subdir.
function f {
cd "$1"
# do something in this dir
for d in * .[!.]* ..?*; do
cd "$1"
test -d "$1/$d" && f "$1/$d"
done
}
f "`pwd`"
For Zsh you'd probably want to set NULL_GLOB option (-G switch), so it doesn't report errors if there are no hidden dirs, in Bash it works by default.
Upvotes: 2
Reputation: 359935
This is based on maarons' answer, but with two advantages:
*/
instead of *
in the for
loop means it only iterates over directories instead of all files for a potentially big speeduppushd
and popd
makes it easy to support .
or no argument to mean the current directory.Here is the function:
g () {
local d bb=/dev/null # bit-bucket
pushd "$1" > $bb
pwd # do something (pwd is a placeholder)
for d in */
do
test -d "$PWD/$d" && g "$PWD/$d" # you could use $(pwd) instead of $PWD
done
popd > $bb
}
Of course, using find
with -execdir
is simpler and gives the same results.:
find -mindepth 1 -type d -execdir sh -c 'cd {}; pwd' \; # (pwd` is a placeholder)
Upvotes: 0
Reputation: 11247
find
is the way to go. You will not learn anything useful choosing the wrong way to solve a problem.
Print a list of files you want to remove
find /your/dir -type f -iname '*.html*'
and delete them
find /your/dir -type f -iname '*.html*' -delete
find
is a powerful command, learn to use it.
Another way to improve the command you don't want to use:
find /your/dir -type f -name '*.html*' -exec rm -f {} +
(hint: man find
to learn how -exec ;
and -exec +
differ)
Note that shell scripting is just using in the best useful way the small programs like find
, cat
, ls
, wc
, etc. Knowing these utilities thoroughly is a necessary requisite to learn shell scripting.
Upvotes: 1
Reputation: 33092
With bash 4 (or zsh) you can use globstar "**" to match recursively.
shopt -s globstar
echo **/*html*
With a directory setup like this:
mkdir -p {a..b}/{c..d}
touch {a..b}/{c..d}/{e..f}.{htmlx,other}
It will result in:
a/c/e.htmlx a/c/f.htmlx a/d/e.htmlx a/d/f.htmlx b/c/e.htmlx b/c/f.htmlx b/d/e.htmlx b/d/f.htmlx
Upvotes: 3
Reputation: 140257
Create a function like so:
myfunc()
{
for dir; do
if [[ -d "$dir" ]]; then
echo rm -rf "${dir}/*.html*"
else
echo "No such dir '$dir'"
fi
done
}
Then call the function by passing the directories you want to remove .html from
$ myfunc /foo /etc /root
No such dir '/foo'
rm -rf /etc/*.html*
rm -rf /root/*.html*
Once you are satisfied with the output, remove the echo
to have it really delete the files.
Upvotes: 0