shell script to delete Files and sub directories from a directory in linux - shell

I want to delete all files and sub directories created by using the specified files. I am currently using the command to delete files and directories
find . ! -name file.txt -type d -exec rm -r {} + #this is for sub directories
find . ! -name file.txt -type f -exec rm -f {} + #this is for files
It deletes all the files and sub directories when I run these command twice but I want to delete all files and directories created leaving one file at once sort. Any help is highly appreciable.
Regards
Jitendra

GNU find can directly delete files and directories:
find ! -name file.txt -delete
It will give error messages, because it cannot delete the directories up to file.txt, but everything else will still be deleted.
If you want to keep the files file1.txt, file2.txt, and file3.txt, chain the conditions like this:
find ! \( -name file1.txt -o -name file2.txt -o -name file3.txt \) -delete

Related

How can I diff two directories in bash recursively for only 1 file name?

Currently I am trying this:
diff -r /develop /us-prod
which shows all the differences between the two, but all I really care about here is a file named schema.json, which is guaranteed to be there in all directories, but this file can be different.
I want to diff these two directories, but only if the file name is schema.json.
I see that you can do -x to exclude files, but it is difficult to say which other files could be in there.
There are some guaranteed files to be there, but some are not. Is there more an "inclusion" than an exclude?
You can try this :
find /develop -type f -name schema.json -exec bash -c\
'diff "$1" "/us-prod${1#/develop}"' _ {} \;
Assuming the both directories have just one schema.json file for each directory
including their subdirectories, would you please try:
diff $(find /develop -type f -name schema.json) $(find /us-prod -type f -name schema.json)

copying files from subfolders via grep shell script

I want to write a shell script to do the following :
I have a folder with many subfolders. Each of these subfolders has a *.gz file and some other files which I don't need. I want to move all .gz files into a new subfolder called needed_files (I have already created this subfolder). So I did the following :
I went to the parent folder with all the subfolder and cp /.gz > needed_files/., but this did not work. Can you suggest what I should be doing?
grep is irrelevant here. Use find:
find . ! \( -type d -name needed_files -prune \) -type f -name '*.gz' \
-exec echo mv -t needed_files {} +
POSIX equivalent of that -exec is
-exec sh -c 'echo mv "$#" needed_files' _ {} +
If its output looks good, remove echo.
Btw I noticed that the title says copy but you also say I want to move, so decide on what you exactly want to do and let me know so I can edit my answer.

Unix script moving files to folders

I have a folder work and the below script searches for .txt or .csv files and moves the files into completed folder. I created one more folder (APEX) inside work folder, but the files from APEX folder are not moving to the completed folder and giving below error. I would like all the .txt or .csv files in my-test-folder/work and my-test-folder/work/APEX files to be moved to my-test-folder/done.I do not have a folder /my-test-folder/completed/APEX/ ,nor I want the files to be moved there.
Error : mv: cannot move ./my-test-folder/work/APEX/test1.txt to ./my-test-folder/completed/APEX/test1.txt: No such file or directory
find . -path "*work*" \( -iname "*.txt" -o -iname "*.csv" \) -exec bash -c "mv {} \`echo {} | sed -e 's/work/completed/g' \` " \;
If you don't want to keep the same directory hierarchy in my-test-folder/completed as in my-test-folder/work, you can simplify your command:
find full/path/to/work -iname "*.txt" -o -iname "*.csv" -exec mv "{}" full/path/to/completed \;
Note that this will not remove empty directories left after moving all the files out. You can do this if you are using GNU find with the following command:
find work -empty -delete

Unix: Batch move files from multiple subdirectories up 1 level

How can I move files from several subdirectories up 1 level in one terminal command?
File Structure:
path/to/files/A/remove/image.png
path/to/files/B/remove/image.png
path/to/files/C/remove/image.png
path/to/files/D/remove/image.png
path/to/files/E/remove/image.png
Desired Structure:
path/to/files/A/image.png
path/to/files/B/image.png
path/to/files/C/image.png
path/to/files/D/image.png
path/to/files/E/image.png
There are A LOT of directories and each "letter" directory above includes several images. Also, would like to delete the directory the files were moved from.
I had the same requirement (on a mac) but in my case the subdirectory did not have the same name as in the original question making it a bit more complicated. This is what worked for me:
from the "path/to" folder I ran
find . -mindepth 3 -maxdepth 3 -type f | awk -v sq="'" -F "/" '{print "mv -i " sq $0 sq " " sq "./" $2 sq}' > moveup.sh
and then
sh moveup.sh
There are many ways to do it.
This moves all files to their grand-parent directory:
$ find path/to/files -type f -exec mv {} $(dirname $(dirname {})) \;
You add a -name \*.type or whatever, instead of the -type f option, in order to be more specific.
This removes empty directories:
$ find . -type d -empty -exec rmdir {} \;
(although it generates benign errors, which I guess is because the directory structure has been altered while find is still working).
I found the solution to my question...
Using the example directories in my original question, I used this command:
for a in $(find path/to/files -maxdepth 1 -type d); do mv $a/remove/* $a/; rmdir $a/remove; done
"remove" is the name of the subdirectory I wanted to move the files out of within each directory.
The answer was actually found here:
https://serverfault.com/questions/405146/how-to-mass-move-files-one-directory-up

Recursively unzip files and then delete original file, leaving unzipped files in place from shell

I've so far figured out how to use find to recursively unzip all the files:
find . -depth -name `*.zip` -exec /usr/bin/unzip -n {} \;
But, I can't figure out how to remove the zip files one at a time after the extraction. Adding rm *.zip in an -a -exec ends up deleting most of the zip files in each directory before they are extracted. Piping through a script containing the rm command (with -i enabled for testing) causes find to not find any *.zips (or at least that's what it complains). There is, of course, whitespace in many of the filenames but at this point syntaxing in a sed command to add _'s is a bit beyond me. Thank for your help!
have you tried:
find . -depth -name '*.zip' -exec /usr/bin/unzip -n {} \; -exec rm {} \;
or
find . -depth -name '*.zip' -exec /usr/bin/unzip -n {} \; -delete
or running a second find after the unzip one
find . -depth -name '*.zip' -exec rm {} \;
thx for the 2nd command with -delete! helped me a lot..
just 2 (maybe helpful) remarks from my side:
-had to use '.zip' instead of `.zip` on my debian system
-use -execdir instead of -exec > this will extract each zip file within its current folder, otherwise you end up with all extracted content in the dir you invoked the find cmd.
find . -depth -name '*.zip' -execdir /usr/bin/unzip -n {} \; -delete
THX & Regards,
Nord
As mentioned above, this should work.
find . -depth -name '*.zip' -execdir unzip -n {} \; -delete
However, note two things:
The -n option instructs unzip to not overwrite existing files. You may not know if the zip files differ from the similarly named target files. Even so, the -delete will remove the zip file.
If unzip can't unzip the file--say because of an error--it might still delete it. The command will certainly remove it if -exec rm {} \; is used in place of -delete.
A safer solution might be to move the files following the unzip to a separate directory that you can trash when you're sure you have extracted all the files successfully.
Unzip archives in subdir based on the file name (../file.zip -> ../file/..):
for F in $(find . -depth -name *.zip); do unzip "$F" -d "${F%.*}/" && rm "$F"; done
I have a directory filling up with zipped csv files. External processes are writing new zipped files to it often. I wish to bulk unzip and remove the originals as you do.
To do that I use:
unzip '*.zip'
find . | sed 's/$/\.zip/g' | xargs -n 1 rm
It works by searching and expanding all zip files presently in the directory. Later, after it finishes there are potentially new unzipped new files mixed in there too that are not to be deleted yet.
So I delete by finding successfully unzipped *.csv files, and using sed to regenerate the original filenames for deletion which is then fed to rm via the xargs command.

Resources