I want to remove files(whose name contains "extract") older than 7 days from various directories in a particular path. If I run the script without any argument the script should be able to delete the files from all the directories inside that particular path. If I run the script using any arguments , then the script should not delete files from those specific directories.
Example :-
Path - /languages/analytics
Let's assume directory "analytics" contains 10 dirctories like c,java,javascript,python,shell,golang,scala,ruby,react,angular.This directory also contains few files along with these 10 directories.
Scenario1 - I want to remove the files older than 7 days from all the 10 directories.
Scenario2 - I want to remove the files older than 7 days from all directories except angular.
Scenario3 - I want to remove the files older than 7 days from all directories except ruby,react,shell.
So basically whatever arguments I pass , the script should not delete files from those particular directories.The number of arguments may vary as per requirement.And if I run without arguments, then the script should delete older files from all the directories in that path.The number of directories may vary as well.
Here is what I have written so far ...
#!/bin/bash
cd /languages/analytics
for f in *; do
if [ -d "$f" ] && [[ "$f" != $1 ]]; then
find /languages/analytics/"$f" -mtime 7 -name '*extract*' -exec rm -f {} \;
fi
done
The above script works fine when I run it without arguments. It runs fine when I pass 1 argument.
sh scriptname -> successfully deletes files from all directories in /languages/analytics path.
sh scriptname ruby -> successfully delete files from all directories except ruby.
Can you please advise how to enhance this script to take as many arguments as possible and the script should not delete files from those particular directories which are passed in the argument ?
CodePudding user response:
With GNU find
try
# /usr/bin/env bash
root=/languages/analytics
exclude=(-name ..) # always FALSE, neutral element of OR
for arg; do
exclude =(-o -samefile "$root/$arg")
done
find "$root" \( "${exclude[@]}" \) -prune -o -mtime 7 -name '*extract*' -delete
For testing you might want to leave out the -delete
first.
For different version of find
, you can use the -exec rm -f {}
instead of -delete
and try -path
instead of -samefile
. But beware! -path
interprets patterns like *
and ?
and fails to recognize that ruby
, ruby/
and are the same thing. But for plain arguments like script.sh ruby golang
you should be fine.
CodePudding user response:
Try this Shellcheck-clean code:
#! /bin/bash -p
for dir in /languages/analytics/*/; do
for arg; do [[ $dir == */"$arg"/ ]] && continue 2; done
find "$dir" -mtime 7 -name '*extract*' -exec rm -f {} \;
done
for arg; do
loops over the positional arguments ($1
,$2
, ...)continue 2
skips to the next iteration of the outer (for dir ...
) loop.
CodePudding user response:
#!/bin/bash
args=("${@}")
mainpath=./languages/analytics
readarray -t datafolders < <(find "$mainpath" -maxdepth 1 -mindepth 1 -type d -print0|xargs -0 -I {} basename {})
for subfolder in "${args[@]}"; do
for i in "${!datafolders[@]}"; do
if [[ ${datafolders[i]} = "$subfolder" ]]; then
unset 'datafolders[i]'
fi
done
done
datafolders=( "${datafolders[@]/#/$mainpath/}" )
declare -p datafolders
# delete command for multiple folders
# find "${datafolders[@]}" -type f -mtime 7 -name '*extract*' -print0 | xargs -0 rm -f
For my test i used "./languages/analytics"
Scenario 1 all directories
$ ./script.sh
declare -a datafolders=([0]="./languages/analytics/ruby" [1]="./languages/analytics/react" [2]="./languages/analytics/scala" [3]="./languages/analytics/java" [4]="./languages/analytics/angular" [5]="./languages/analytics/javascript" [6]="./languages/analytics/python" [7]="./languages/analytics/shell" [8]="./languages/analytics/golang" [9]="./languages/analytics/c")
Scenario 2 except angular
$ ./script.sh angular
declare -a datafolders=([0]="./languages/analytics/ruby" [1]="./languages/analytics/react" [2]="./languages/analytics/scala" [3]="./languages/analytics/java" [4]="./languages/analytics/javascript" [5]="./languages/analytics/python" [6]="./languages/analytics/shell" [7]="./languages/analytics/golang" [8]="./languages/analytics/c")
Scenario 3 except ruby react shell
$ ./script.sh execpt ruby react shell
declare -a datafolders=([0]="./languages/analytics/scala" [1]="./languages/analytics/java" [2]="./languages/analytics/angular" [3]="./languages/analytics/javascript" [4]="./languages/analytics/python" [5]="./languages/analytics/golang" [6]="./languages/analytics/c")