I want to rename all .hg_gg folders in /var/www to .hg. How can I do it?
I know how to rename .hg to .hg_gg.
find /var/www -name ".hg" -exec bash -c 'mv $0 $0_gg' {} \;
but don't know how to make reverse change.
Try this:
find /var/www -name ".hg_gg" -execdir bash -c 'mv {} .hg' \;
You need to use a special syntax defined by find: {} is the placeholder for the current file name. Check the man page for that. Also it is important to use -execdir instead of -exec. execdir changes the current working directory to the folder where the found directory is located. Otherwise it would do something like this mv /var/www/.hg_gg ./.hg
You can speed up things a bit when restricting find to find folders only using -type d:
find /var/www -type d -name ".hg_gg" -execdir bash -c 'mv {} .hg' \;
Consider this find command with -execdir and -prune options:
find /var/www/ -type d -name ".hg_gg" -execdir mv '{}' '.gg' \; -prune
-execdir will execute the command in each subdirectory
-prune causes find to not descend into the current file
Not a one liner, but you could do this:
for file in `find /var/www -name ".hg_gg"`; do
mv $file `echo $file | sed 's/hg_gg$/hg/'`
done
Related
How to recursively recode all project files excluding some directories and preserving permissions?
Based on this question, but its solution does not preserve permissions, so I had to modify it.
WARNING: since the recursive removal is a part of the solution, use it on your own risk
Task:
Recursively recode all project files (iso8859-8 -> utf-8) excluding '.git' and '.idea' dirs and preserving permissions.
Solution (worked well in my case):
Backup your project's dir, then cd there. Run:
find . -not -path "./.git/*" -not -path "./.idea/*" -type f -print -exec iconv -f iso8859-8 -t utf-8 -o {}.converted {} \; -exec sh -c 'cat {}.converted > {}' \; -exec rm {}.converted \;
Binary and image files will fail to recode since they aren't text, so files like 'image.jpeg.converted' will be left along with 'image.jpeg'. To clean up this mess:
find . -not -path "./.git/*" -not -path "./.idea/*" -type f -regex '.*\.converted' -exec rm {} \;
Before you do that, you may want just print (without rm) to see that there are only those files listed that you'd really like to remove.
Is there a way to remove all temp files and executables under one folder AND its sub-folders?
All that I can think of is:
$rm -rf *.~
but this removes only temp files under current directory, it DOES NOT remove any other temp files under SUB-folders at all, also, it doesn't remove any executables.
I know there are similar questions which get very well answered, like this one:
find specific file type from folder and its sub folder
but that is a java code, I only need a unix command or a short script to do this.
Any help please?
Thanks a lot!
Perl from command line; should delete if file ends with ~ or it is executable,
perl -MFile::Find -e 'find(sub{ unlink if -f and (/~\z/ or (stat)[2] & 0111) }, ".")'
You can achieve the result with find:
find /path/to/directory \( -name '*.~' -o \( -perm /111 -a -type f \) \) -exec rm -f {} +
This will execute rm -f <path> for any <path> under (and including) /path/to/base/directory which:
matches the glob expression *.~
or which has an executable bit set (be it owner, group or world)
The above applies to the GNU version of find.
A more portable version is:
find /path/to/directory \( -name '*.~' -o \( \( -perm -01 -o -perm -010 -o -perm -0100 \) \
-a -type f \) \) -exec rm -f {} +
find . -name "*~" -exec rm {} \;
or whatever pattern is needed to match the tmp files.
If you want to use Perl to do it, use a specific module like File::Remove
This should do the job
find -type f -name "*~" -print0 | xargs -r -0 rm
I'm trying to use find to remove all files under cache directories in a web hosted environment.
find /home/hosted -maxdepth 2 -type d -name "cache" -print -exec rm -rf "{}/*" \;
I've tried several variations of this, but for some reason find won't remove the cache/* files. Anyone see anything I'm missing?
Thanks
Arguments for -exec don't get expanded as you expect. That is because -exec calls execve() directly and thus * does not get expanded to all files in a matching directory. If you want to have shell expansion, you have to feed -exec with /bin/sh (or a shell of your choice), like this:
find /your/dir -name "cache" -type d -maxdepth 2 -print -exec sh -c "rm -f {}/*" \;
I need to delete unpacked directories from my /source tree keeping the others with .tar and .patch extensions,
how to do please?
This should work:
find . -not -name "*.tar" -not -name "*.patch" -type f -exec rm {} \;
This is using only one command not using pipes.
Note. This will proceed recursively into subdirectories. If this is unwanted, use the maxdepth switch:
find . -maxdepth 1 -not -name "*.tar" -not -name "*.patch" -type f -exec rm {} \;
BACKUP YOUR DIRECTORY FIRST, I HAVE NOT TESTED THIS, AND IT HAS A BUG AS NOTED IN THE COMMENTS.
WHILE IN THE ACTUAL /source DIRECTORY:
ls|fgrep -v -e .tar -e .patch|xargs rm -rf
You probably want to use the "put echo after xargs" trick to see what this would actually do, before running it:
ls|fgrep -v -e .tar -e .patch|xargs echo rm -rf
I'm on a linux system I wonder what is wrong with the following execution of find:
mkdir a && touch a/b
find . -name a -type d -exec echo '{}' \;
./a
find . -name a -type d -exec rm -r '{}' \;
find: `./a': No such file or directory
The invocation of echo is just for testing purposes. I would expect the last command to remove the directory './a' entirely and return 0. Instead it removes the directory and generates the error message. To repeat, it does remove the directory! What is going on?
rm executes without a problem. The issue is that find is confused, since it knew the directory ./a was there, it tries to visit that directory to look for directories named a. However, find cannot enter the directory, since it was already removed.
One way to avoid this is to do
find -name a -type d | xargs rm -r
This will let the find move along before the rm command is executed. Or, you can simply ignore the error in your original command.
Based on epsalon's comment the solution is to use the -depth option which causes the deeper files to be visited first.
find . -depth -name a -type d -exec rm -r '{}' \;
does the trick. Thanks a bunch!
If performance is an issue, use -prune in order to prevent find from descending into directories named "a":
find . -name a -type d -prune -exec rm -r '{}' \;