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

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

Related

renaming the files recursively in unix

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

unix: count number of jpeg files recursively except for one subfolder in every folder?

I think the code to count all the jpeg files recursively in a folder is,
find . -type f -name "*.jpeg" | wc -l
but I now realize I need to exclude some subfolders...
for instance, my folder consists of 5 subfolders and in each subfolder there is a subsubfolder named "meh" consisting of jpeg files I wish not to include in my count... Could anyone let me know how to do that?
Thanks so much for your guidance.
You can do this with find's option -prune or -regex.
find . -name meh -prune -o -name '*.jpeg' -print | wc -l
find . -not -regex '.*/meh/.*' -a -name '*.jpeg' -print | wc -l
Weird that #Prune didn't answer that.
Since find includes the relative path of each file, you could do this:
find . -type f -name "*.jpeg" | grep -vc /meh/
Use any grep variant to filter the output of find.
While you're doing that, use the count option from grep, -c.
-v is reverse logic: list only those that do not match the given pattern.
find . -type f -name "*.jpeg" | egrep -c -v "/meh/"

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 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]

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