How to keep certain folders and delete rest in Unix - unix

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]

Related

Searching for particular files in a directory non-recursively using find. AIX

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.

How do you move all files and folders within a directory to the parent directory?

How do you move all files and folders within a directory from their sub directories to the parent directory? Including files within very deep folder directories.
What I would like to achieve is for when I am at . to convert this:
.
./aDir
./aDir/bFile
./aDir/cDir
./aDir/cDir/dDir
./aDir/cDir/dDir/eFile
To this:
.
./aDir
./bFile
./cDir
./dDir
./eFile
I assume you use the unix command find however I can't seem to get it to work.
Here's what I tried:
find -mindepth 1 -maxdepth * -print0 | xargs -0 mv -i -t ~/Desktop
Since you are looking to un-nest your directory you'll need to mv them in depth first order, otherwise deeper directories could be mv'd inside the shallower ones.
Using very similar syntax to your attempt the following seems to do what is required.
find . -mindepth 2 -depth -type d -print0 | xargs -0 -I{} mv {} ~/Desktop
Example:
$ find . -mindepth 1 -depth -type d
./a/b/c2
./a/b/c
./a/b
./a
$ find . -mindepth 2 -depth -type d -print0 | xargs -0 -I{} mv {} .
$ find . -mindepth 1 -depth -type d
./a
./b
./c
./c2
Maybe this helps:
for i in $(find .); do cp -r $i .; done
When you are at . it converts this:
.
./a
./a/b
./a/b/c
To this:
.
./a
./a/b
./a/b/c
./c
./b
./b/c
Try this
find . -maxdepth 1 -exec mv {} .. \;
you might get this message
mv: cannot move `.' to `../.': Device or resource busy
But don't worry it is because '.' this directory is being attempted to move.
I think you want:
find . -mindepth 1 -depth -print0 | xargs -0 mv -i -t ~/Desktop

Bash, find and delete whilst retaining directory

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.

How to delete only directories and leave files untouched

I have hundreds of directories and files in one directory.
What is the best way deleting only directories (no matter if the directories have anything in it or not, just delete them all)
Currently I use ls -1 -d */, and record them in a file, and do sed, and then run it. It rather long way. I'm looking for better way deleting only directories
To delete all directories and subdirectories and leave only files in the working directory, I have found this concise command works for me:
rm -r */
It makes use of bash wildcard */ where star followed by slash will match only directories and subdirectories.
find . -maxdepth 1 -mindepth 1 -type d
then
find . -maxdepth 1 -mindepth 1 -type d -exec rm -rf '{}' \;
To add an explanation:
find starts in the current directory due to . and stays within the current directory only with -maxdepth and -mindepth both set to 1. -type d tells find to only match on things that are directories.
find also has an -exec flag that can pass its results to another function, in this case rm. the '{}' \; is the way these results are passed. See this answer for a more complete explanation of what {} and \; do
First, run:
find /path -d -type d
to make sure the output looks sane, then:
find /path -d -type d -exec rm -rf '{}' \;
-type d looks only for directories, then -d makes sure to put child directories before the parent.
Simple way :-
rm -rf `ls -d */`
find command only (it support file deletion)\
find /path -depth -type d -delete
-type d looks only for directories, then -depth makes sure to put child directories before the parent. -delete removing filtered files/folders
In one line:
rm -R `ls -1 -d */`
(backquotes)

How do I delete certain files in the current directory that doesn't match the given pattern?

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

Resources