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

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

Related

unix find command in terminal does not work

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.

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

How to keep certain folders and delete rest in 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]

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 move or copy files listed by 'find' command in unix?

I have a list of certain files that I see using the command below, but how can I copy those files listed into another folder, say ~/test?
find . -mtime 1 -exec du -hc {} +
Adding to Eric Jablow's answer, here is a possible solution (it worked for me - linux mint 14 /nadia)
find /path/to/search/ -type f -name "glob-to-find-files" | xargs cp -t /target/path/
You can refer to "How can I use xargs to copy files that have spaces and quotes in their names?" as well.
Actually, you can process the find command output in a copy command in two ways:
If the find command's output doesn't contain any space, i.e if the filename doesn't contain a space in it, then you can use:
Syntax:
find <Path> <Conditions> | xargs cp -t <copy file path>
Example:
find -mtime -1 -type f | xargs cp -t inner/
But our production data files might contain spaces, so most of time this command is effective:
Syntax:
find <path> <condition> -exec cp '{}' <copy path> \;
Example
find -mtime -1 -type f -exec cp '{}' inner/ \;
In the second example, the last part, the semi-colon is also considered as part of the find command, and should be escaped before pressing Enter. Otherwise you will get an error something like:
find: missing argument to `-exec'
find /PATH/TO/YOUR/FILES -name NAME.EXT -exec cp -rfp {} /DST_DIR \;
If you're using GNU find,
find . -mtime 1 -exec cp -t ~/test/ {} +
This works as well as piping the output into xargs while avoiding the pitfalls of doing so (it handles embedded spaces and newlines without having to use find ... -print0 | xargs -0 ...).
This is the best way for me:
cat filename.tsv |
while read FILENAME
do
sudo find /PATH_FROM/ -name "$FILENAME" -maxdepth 4 -exec cp '{}' /PATH_TO/ \; ;
done

Resources