I am trying my hand at some Bash scripting and any help would be appreciated.
The script is supposed to find all users users in /Users/ and delete everything inside. Movies, Documents, Desktop and Music.
Whilst still retaining the directory essentially emptying it. Also excluding the user files of ladmin, shared and Guest.
When I execute. It doesn't empty the files though I get the feed back I would expect. Am I missing something simple here?
DIR_CD=/Users/
cd $DIR_CD
find . -type d ! -name "*ladmin*" ! -name "*Guest*" ! -name "*Shared*" \
-maxdepth 1 -print -exec rm -rf {}/Desktop/* \;
find . -type d ! -name "*ladmin*" ! -name "*Guest*" ! -name "*Shared*" \
-maxdepth 1 -print -exec rm -rf {}/Documents/* \;
find . -type d ! -name "*ladmin*" ! -name "*Guest*" ! -name "*Shared*" \
-maxdepth 1 -print -exec rm -rf {}/Movies/* \;
find . -type d ! -name "*ladmin*" ! -name "*Guest*" ! -name "*Shared*" \
-maxdepth 1 -print -exec rm -rf {}/Music/* \;
Like this?
for d in /Users/*; do
case ${d#*/} in ladmin | Guest | Shared ) continue ;; esac
rm -rf "$d"/Desktop/* "$d"/Documents/* "$d"/Movies/* "$d"/Music/*
done
With Bash extended globbing you could do it all with a single wildcard expression.
Related
i know this would be marked as a duplicate one, but i tried searching google and what i'm trying is not working for me.
I've some .txt files in a directory, i need to rename all the *.txt files to *_XYZ.txt recursively. XYZ is defined in a variable X.
I've tried below code:
file=`find ./ -type f -name "*.txt"|sed "s,^./,,g" |awk -F '.' '{print $1}'`
for i in "$file"
do
mv "$i" "$i_${X}.txt"
done
Any help would be greatly appreciated.
Thanks.
Your script destroys original filenames in variable file, this is why it cannot rename files.
Working example:
X="_XYZ"
for f in $(find . -type f ! -name "*$X.txt" -name "*.txt"); do
mv "$f" "${f%.txt}$X.txt"
done
Output:
$ X="_XYZ"
$ find . -type f -name "*.txt"
./c_XYZ.txt
./aa/c.txt
./a.txt
./b.txt
$ for f in $(find . -type f ! -name "*$X.txt" -name "*.txt"); do mv "$f" "${f%.txt}$X.txt"; done
$ find . -type f -name "*.txt"
./b_XYZ.txt
./c_XYZ.txt
./aa/c_XYZ.txt
./a_XYZ.txt
I have a script which has the following command. I am trying to edit this in such a way that it only searches the files in the directory of the path without going in the subdirectories. That is not recursive search
find {Path} -name "cor*" -type f -exec ls -l {} \;
Example: The command should give cor123.log only and not cor456.log. Currently it gives both
<Path>
..cor123.log
<directory>
..cor456.log
I tried using -maxdepth but it's not supported in AIX. -prune and -depth didn't help either.
Will appreciate any help. Thanks
You can use
find . -name . -o -prune
to find files and directories non-recursively.
So in your case this one will work:
find . -name . -o -prune -name 'cor*' -type f -exec ls -l {} \;
Do you need find for selecting files only?
When you know that all files starting with cor are regula files, you can use
ls -l ${Path}/cor*
or
ls -l ${Path}/cor*.log
When you need the -type f, you can try to filter the results.
The filename can not have a /, so remove everything with an / after the Path.
We do not know the last char of ${Path}. It can be /, which will make the grep -Ev "${Path}/.*/" filter useless. After the Path at least one character is needed before looking for the next /.
find "${Path}" -name "cor*" -type f 2>/dev/null| grep -Ev "${Path}..*/" | xargs -ls
Late answer but may save some. In aix
find /some/directory/* -prune -type f -name *.log
For instance make your path have the last forward slash with a wildcard then -prune
/*
find /some/directory/* -prune -name "cor*" -type f -exec ls -l {} \
Tested.
I need to place a command that will search for all files in the current directory as well as in its sub-directories - ending by ~, and/or all files that start or end by #. The command line will show and erase all files found. Only one command is allowed: no ’;’ or ’&&’ or other shenanigans.
here is my command:
find . -name "#*" -o -name "*#" -o -name "*~" -print -delete
but it erases only the files ending in ~
You forgot to enclose the conditions with parenthesis (). This means that only the last condition will trigger the actions -print and -delete.
The default is and -a, which would not require the parenthesis, that's why most find commands such as find -type f -name "pattern" -print works without parenthesis.
You should try:
find . \( -name "#*" -o -name "*#" -o -name "*~" \) -print -delete
How about -print0 primary in conjunction with xargs -0'' like this .
find . -type f -print0 | xargs -0 rm
za:temp za$ ls
file.txt file.txt~
za:temp za$ find . -name "*~" -print0 | xargs -0 rm
za:temp za$ ls
file.txt
Or with xargs -I {} plus your comand which does the same thing .
# xargs -I {} to capture the value of find
find . -iname *something* | xargs -I {} rm {}
edit : if you can't see the files that start with # using find . then the files have spaces within the name of the file(s) like # file.txt. you will need to find files with spaces with something like find . -name "* *" and then remove the spaces.
I have around 10 folders and I am trying to keep only few subfolders under these and delete the rest.
Example: I have
A/1
A/2
A/3
A/4
B/1
B/4
B/5
B/6
I am trying to keep only the folder 1 and 4 under each parent folder A and B. I am using find -type d -name 2 -exec rm -rf {} \; to find and delete each folder.
Is there any unix command to just keep the folder 1 and 4 and delete the rest?
Tell find exactly what you are looking for;
find . -mindepth 2 -type d -name "[^14]" -exec rm -rf {} \;
Excluding directories 1 and 4, at the child level, find the other directories and delete them.
AIG's idea to exclude is probably correct, but the way to exclude with find is with the -o (or) operator, which stops if what came before is true and continues otherwise:
find . -mindepth 2 -type d -name 1 -o -name 4 -o -exec rm -rf {} +
I believe this works for posix compliant systems:
find . -type d -links 2 \! \( \( -name 1 \) -o \( -name 4 \) \) -exec rm -rf {} \;
This includes only child directories and excludes directories named 1 or 4.
Using just glob
$ rm -rf [AB]/[^14]
using rm *.sh to delete files ending in .sh is easy and understandable. But how do i delete all files in the current directory that does not end in .jar
something like rm * -except *.jar
Try this:
find . -mindepth 1 -maxdepth 1 ! -name '*.jar' | sort
If you really want to delete all the files in its output, then just do
find . -mindepth 1 -maxdepth 1 ! -name '*.jar' -delete
You can read the find(1) manual page for more information on this really powerful tool.
EDIT:
Since the -delete flag is only found in GNU find > 4.2.3 (as pointed out by SiegeX), here are a couple of alternatives, which also make sure we are not trying to delete directories:
find . -mindepth 1 -maxdepth 1 ! -type d ! -name '*.jar' -print0 | xargs -0 -r rm -f
The -r xargs flags is a GNU extension, so this is slightly more portable (it works on *BSD), but not as clean:
find . -mindepth 1 -maxdepth 1 ! -type d ! -name '*.jar' -print0 | xargs -0 rm -f
As a last - but most portable - resort:
find . -mindepth 1 -maxdepth 1 ! -type d ! -name '*.jar' -exec rm '{}' ';'
This has the disadvantage of invoking rm separately for each file, which makes it significantly slower.
echo $(ls | grep -v '.jar$')
rm $(ls | grep -v '.jar$')
You can do this by enabling the extended glob extglob option and then putting your pattern inside !() like so:
shopt -s extglob;
rm !(*.jar)
Note that extglob also gives you the following:
?() -- Match zero or one of the pattern
*() -- Match zero or more of the pattern
#() -- Match exactly one of the pattern
!() -- Match anything except the pattern