Searching Directories and Removing Folders and Files in Bash - bash

I have a bash script that goes into a components/ and runs the following command:
cp -R vendor/* .
I then have a second command that traverses any folder, accept the vendor folder , inside the components directory lookinf got .git/, '.gitignore' and Documentation/ and removes them. How ever:
I don't thinks it's recursive
It doesn't actually remove those files and directories either because of the top point or because of permissions (should I add a sudo)?
A directory copied from vendor might look like:
something/
child-directory/
.git/ // -- Should be removed.
The command in question is:
find -name vendor -prune -o \( -name ".git" -o -name ".gitignore" -o -name "Documentation" \) -prune -exec rm - rf "{}" \; 2> /dev/null || true
Now if it is a permission error, I wont know about it because I want it to ignore any errors and continue with the script.
Any thoughts?

I think the problem is in the option -prune. Anyways, this might work for you...
find vendor -name '.git' -o -name '.gitignore' -o -name 'Documentation' | xargs rm -rf

Related

Delete node_modules folder recursively from a specified path using command line

I have multiple npm projects saved in a local directory. Now I want to take backup of my projects without the node_modules folder, as it is taking a lot of space and can also be retrieved any time using npm install.
So, what would be a solution to delete all node_modules folders recursively from a specified path using the command line interface?
Print out a list of directories to be deleted:
find . -name 'node_modules' -type d -prune
Delete directories from the current working directory:
find . -name 'node_modules' -type d -prune -exec rm -rf '{}' +
Alternatively you can use trash (brew install trash) for staged deletion:
find . -name node_modules -type d -prune -exec trash {} +
Try
https://github.com/voidcosmos/npkill
npx npkill
it will find all node_modules and let you remove them selectively.
Improving on the accepted answer:
find . -name 'node_modules' -type d -prune -exec rm -rf '{}' +
I found that the command above would run a very long time to fetch all folders and then run a delete command. To make the command resumable, I'd suggest using \;. To see progress of the command being run, use -print to see the directory being deleted.
Note: You must first cd into the root directory and then run the command. Or instead of find ., use find {project_directory}.
To delete folders one by one:
find . -name 'node_modules' -type d -prune -exec rm -rf '{}' \;
To delete folders one by one and print the folder being deleted:
find . -name 'node_modules' -type d -prune -print -exec rm -rf '{}' \;
For the people who like an interactive way of doing this, refer to jeckep's answer. Run this in the directory you wish to prune:
npx npkill
I have come across with this solution,
first find the folder using find and specify name of the folder.
execute delete command recursively -exec rm -rf '{}' +
run the following command to delete folders recursively
find /path -type d -name "node_modules" -exec rm -rf '{}' +
When on Windows, I use the following .BAT file to delete node_modules recursively from the current folder:
#for /d /r . %d in (node_modules) do #if exist %d (echo %d && rd %d /s /q)
Or, via CMD.EXE:
>cmd.exe /c "#for /d /r . %d in (node_modules) do #if exist %d (echo "%d" && rd "%d" /s /q)""
bash function to remove node_modules. It will remove all node_modules directories recursively from the current working directory,
while printing found paths.
You just need to put in somewhere in your $PATH
rmnodemodules(){
find . -name 'node_modules' -type d -prune -exec echo '{}' \; -exec rm -rf {} \;
}
In Bash, you can simply use
rm -rf node_modules **/node_modules
If you want to move instead of delete it:
find . -name 'node_modules' -type d -prune -exec mkdir -p ./another/dir/{} \; -exec mv -i {} ./NODE_MODULES/{} \;
This will keep the directory structure.
A simple trick to remove all node_modules folders in your servers (which can reduce a lot of space) is to run:
# For Ubuntu
sudo find / -not -path "/usr/lib/*" -name 'node_modules' -type d -prune -exec rm -rf '{}' +
# For macOS
sudo find / -not -path "/usr/local/*" -name 'node_modules' -type d -prune -exec rm -rf '{}' +
Here we need to exclude /usr/lib/* because if you won’t, it will delete your npm and you need to reinstall it :)
Note: This is just improving on the accepted answer, please use the accepted answer first.
If you are so bored then keep reading.
Basically, this command should work fine for 99% of cases
find . -name 'node_modules' -type d -prune -exec rm -rf '{}' +
I notice that deleting files via the command line is longer than deleting a folder via Finder (when deleting from Finder it moves that folder to ~/.Trash directory).
So if you want to move node_modules to ~/.Trash folder then you can try
find . -name 'node_modules' -type d -prune -exec sh -c 'mv -f "$1" "$(dirname "$1")/$(basename $(dirname "$1"))_$(basename "$1")" && mv "$(dirname "$1")/$(basename $(dirname "$1"))_$(basename "$1")" ~/.Trash/' sh {} \;
as you notice it consist of 2 parts.
find . -name 'node_modules' -type d -prune find all node_module dirs
-exec sh -c 'mv -f "$1" "$(dirname "$1")/$(basename $(dirname "$1"))_$(basename "$1")" && mv "$(dirname "$1")/$(basename $(dirname "$1"))_$(basename "$1")" ~/.Trash/' sh {} \; rename node_module by prefixing it with it's parent folder name and move it to Trash
Before I had
~/Development/angular-projects
┣ project1
┣ project2
┗ project3
After running command
~/.Trash
┣ ~project1_node_modules
┣ ~project2_node_modules
┗ ~project3_node_modules
Then make sure to empty trash
Or Turn On empty trash feature
Python Script to Delete the node_modules folder from multiple projects. Just place it in your project folder consisting multiple projects and run it.
import os
import shutil
dirname = '/root/Desktop/proj' #Your Full Path of Projects Folder
dirfiles = os.listdir(dirname)
fullpaths = map(lambda name: os.path.join(dirname, name), dirfiles)
dirs = []
for file in fullpaths:
if os.path.isdir(file): dirs.append(file)
for i in dirs:
dirfiles1 = os.listdir(i)
fullpaths1 = map(lambda name: os.path.join(i, name), dirfiles1)
dirs1 = []
for file in fullpaths1:
if os.path.isdir(file):
dirs1.append(file)
if(file[-12:]=='node_modules'):
shutil.rmtree(file)
print(file)

Why is this command exploding

So I got this as an answer to a previous question as an answer for looking recursively through files in a directory and deleting the files and directories if found:
find \( -name ".git" -o -name ".gitignore" -o -name "Documentation" \) -exec rm -rf "{}" \;
There are two problems with this:
One:
find: `./adam.balan/AisisAjax/.git': No such file or directory
because of this error the rest of the script doesn't execute. Now I don't want to have to check for any of the files or folders. I don't care if they exist or not, I want to suppress the error on this.
The second is that I am also getting the error on a directory that needs to be excluded from this search: vendor/
find: `./vendor/adam.balan/AisisAjax/.git': No such file or directory
I do not want it searching vendor. I want it to leave vendor alone.
How do I solve these two problems? Suppression and ignoring.
The problem is that you're deleting a directory that find then tries to descend into. You can use -prune to prevent that:
find \( -name ".git" -o -name ".gitignore" -o -name "Documentation" \) -prune -exec rm -rf "{}" \;
To ignore all errors, you can use 2> /dev/null to squash the error messages, and || true to avoid set -e making your script exit:
find \( -name ".git" -o -name ".gitignore" -o -name "Documentation" \) -prune -exec rm -rf "{}" \; 2> /dev/null || true
Finally, to avoid descending any directory named 'vendor', you can use -prune again:
find -name vendor -prune -o \( -name ".git" -o -name ".gitignore" -o -name "Documentation" \) -prune -exec rm -rf "{}" \; 2> /dev/null || true

Recursive erase hidden files

I'm trying to recursive erase all files that begin with "._" (aka mac dot files) on my server using SSH.
The files are listed with a ls -a but this won't work:
rm -rf ._*
I know there's a way. Mind to share?
Cheers!
find . -name ._\* -print0 | xargs -0 rm -f
find . -name ._\* -type f -delete
Specify that it's files and just call the find-delete on item directly.
find . -name ._\* -exec rm -f {} \;
by the way rm -rf is for removing directories recursively

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.

How do I remove all .pyc files from a project?

I've renamed some files in a fairly large project and want to remove the .pyc files they've left behind. I tried the bash script:
rm -r *.pyc
But that doesn't recurse through the folders as I thought it would. What am I doing wrong?
find . -name "*.pyc" -exec rm -f {} \;
find . -name '*.pyc' -type f -delete
Surely the simplest.
Add to your ~/.bashrc:
pyclean () {
find . -type f -name "*.py[co]" -delete
find . -type d -name "__pycache__" -delete
}
This removes all .pyc and .pyo files, and __pycache__ directories. It's also very fast.
Usage is simply:
$ cd /path/to/directory
$ pyclean
In current version of debian you have pyclean script which is in python-minimal package.
Usage is simple:
pyclean .
If you're using bash >=4.0 (or zsh)
rm **/*.pyc
Note that */*.pyc selects all .pyc files in the immediate first-level subdirectories while **/*.pyc recursively scans the whole directory tree. As an example, foo/bar/qux.pyc will be deleted by rm **/*.pyc but not by */*.pyc.
The globstar shell options must be enabled. To enable globstar:
shopt -s globstar
and to check its status:
shopt globstar
For windows users:
del /S *.pyc
I used to use an alias for that:
$ which pycclean
pycclean is aliased to `find . -name "*.pyc" | xargs -I {} rm -v "{}"'
find . -name '*.pyc' -print0 | xargs -0 rm
The find recursively looks for *.pyc files. The xargs takes that list of names and sends it to rm. The -print0 and the -0 tell the two commands to seperate the filenames with null characters. This allows it to work correctly on file names containing spaces, and even a file name containing a new line.
The solution with -exec works, but it spins up a new copy of rm for every file. On a slow system or with a great many files, that'll take too long.
You could also add a couple more args:
find . -iname '*.pyc' -print0 | xargs -0 --no-run-if-empty rm
iname adds case insensitivity, like *.PYC . The no-run-if-empty keeps you from getting an error from rm if you have no such files.
$ find . -name '*.pyc' -delete
This is faster than
$ find . -name "*.pyc" -exec rm -rf {} \;
Further, people usually want to remove all *.pyc, *.pyo files and __pycache__ directories recursively in the current directory.
Command:
find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf
Django Extension
Note: This answer is very specific to Django project that have already been using Django Extension.
python manage.py clean_pyc
The implementation can be viewed in its source code.
Just to throw another variant into the mix, you can also use backquotes like this:
rm `find . -name *.pyc`
full recursive
ll **/**/*.pyc
rm **/**/*.pyc
Now there is a package pyclean on PyPI, which is easy to use, and cross-platform. User just need a simple command line to clean all __pycache__ files in current dir:
pyclean .
if you don't want .pyc anymore you can use this single line in a terminal:
export PYTHONDONTWRITEBYTECODE=1
if you change your mind:
unset PYTHONDONTWRITEBYTECODE
First run:
find . -type f -name "*.py[c|o]" -exec rm -f {} +
Then add:
export PYTHONDONTWRITEBYTECODE=1
To ~/.profile
rm -r recurses into directories, but only the directories you give to rm. It will also delete those directories. One solution is:
for i in $( find . -name *.pyc )
do
rm $i
done
find will find all *.pyc files recursively in the current directory, and the for loop will iterate through the list of files found, removing each one.
find . -name "*.pyc"|xargs rm -rf
If you want to delete all the .pyc files from the project folder.
First, you have
cd <path/to/the/folder>
then find all the .pyc file and delete.
find . -name \*.pyc -delete
You can run find . -name "*.pyc" -type f -delete.
But use it with precaution. Run first find . -name "*.pyc" -type f to see exactly which files you will remove.
In addition, make sure that -delete is the last argument in your command. If you put it before the -name *.pyc argument, it will delete everything.
To delete all the python compiled files in current directory.
find . -name "__pycache__"|xargs rm -rf
find . -name "*.pyc"|xargs rm -rf
If you want remove all *.pyc files and __pycache__ directories recursively in the current directory:
with python:
import os
os.popen('find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf')
or manually with terminal or cmd:
find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf
py3clean works for me!
cd /usr/local/lib/python3.9
sudo py3clean -v .
Had to add a few ignore params on M1:
pyclean --verbose . --ignore "Library",".Trash"

Resources