Remove all sub-directories and files except for one - linux

I have a folder structure as follows:
/home/user/<individual_user>
In some of the <individual_user> folders there is a .bashrc file that I want to keep, however I want to remove all files and folders under /home/user/<individual_user> except that .bashrc file. All other files and subdirectories under <individual_user> should be deleted. There is an undetermined number of <individual_user> folders.
I would prefer to execute this command as a one-liner under cron.

After your edit, you can use:
find /home/user -mindepth 2 -not -path '*/.bashrc' -print
Once you are satisfied with the output, you can replace -print with -delete to make it:
find /home/user -mindepth 2 -not -path '*/.bashrc' -delete

How about this:
find /home/user ! -name .bashrc -exec rm -rf {} +
For obvious reasons, I haven't tested it ;)

Related

What is the command to remove files in Linux from a particular directory which are owned by a particular user?

Let's say we have a directory path /home/username. How can we delete all the files only from this path which are owned/created by the user dev-user? When I am trying
find . -user c70945a -exec rm /home/dev-user/* {} \;
but it's giving an error and it's removing files from other directories as well.
find /home/username -maxdepth 1 -type f -user "dev-user" -delete
Use the user flag to specify files owner by a specific user and use -delete to remove the files.
Set maxdepth 1 to search for files within /home/username only and not child directories.
Use this find command:
find /home/dev-user -user 'dev-user' -type f -exec rm {} +
+ at the end of -exec means that {} is expanded to the list of all matching files.

Linux move files from dir to dir by name mask

I am trying to move all files with names starts with SML from directory to another.
Tried with
find /var/.../Images/ -name SML\* mv /var/.../Images/Small but doesnt work
try find /var/.../Images/ -name SML\* -exec mv {} /var/.../Images/Small/ \;
I guess you want something like this:
dir=/path/to/your/Images
mkdir -p "$dir/Small"
find "$dir" -name "SML*" -not -wholename "$dir/Small/*" -exec mv {} "$dir/Small/" \;
Since the directory you move the files to is a subdirectory of the one you seach in, you need to exclude the files already moved there. So I added -not -wholename "$dir/Small/*"
To execute a command for each found file, you need -exec .... The alternative would be to pipe your find results to a while read loop.
When using -exec, the found name can be referenced by {}.
See man find for a lot more information.

How to loop through multiple folder and subfolders and remove file name start with abc.txt and 14 days old

I have folder and subfolder. I need to loop through each folder and subfolder and remove or move the file names which start with abc.txt and 14 days old to temporary folder. My folder tree structure is:
The file may be inside the folder or subfolder 'abc.txt'
I have used this below code but not working.
I took the folder paths into a list.txt file using below command
find $_filepath -type d >> folderpathlist.txt
I pass the path list to below code to search and remove or move files to temporary folder
find folderpathlist.txt -name "abc*" -mtime \+14 >>temp/test/
How do I achieve this scenario ?
You want to find files: -type f
that start with abc.txt: -name "abc.txt*"
that are 14 days old: -mtime +14
and move them to a dir.: -exec mv {} /tmp \;
and to see what moved: -print
So the final command is:
find . -type f -name "abc.txt*" -mtime +14 -exec mv {} /tmp \; -print
Adjust the directory as required.
Note that mtime is the modification time. So it is 14 days old since the last modification was done to it.
Note 2: the {} in the -exec is replaced by each filename found.
Note 3: \; indicates the termination of the command inside the -exec
Note 4: find will recurse into sub-directories anyway. No need to list the directories and loop on them again.

Is there a way to specify exceptions to exclusions in the find command via Bash?

I would like to find all of the files within a directory and its subdirectories except for any settings files and anything in settings or dependency directories.
For example, I want to exclude from my results entire directories like .git, .idea, and node_modules as well as files like .DS_Store and config.codekit, but I want to include .gitignore.
What I want is something like the results of the following Git command, but including any untracked files and able to be easily and safely operated upon (e.g., to change permissions).
git ls-tree -r master --name-only
Here is what I have so far and although it is rather unwieldy it seems to mostly do what I want except for leaving out .gitignore:
find . -type f -not -name ".*" -not -name config.codekit -not -path "./.*" -not -path "./node_modules/*"
I have experimented with -prune without much success.
Is there a way to specify exceptions to exclusions in the find command via Bash—to say something like exclude all the things that match this pattern EXCEPT this thing or these things?
By the way, I am presently using OS X, but I also use Ubuntu and I plan to try Ubuntu on Windows when the Windows 10 Anniversary Update is generally available, so ideally I would like to have a command that works across all of those.
Thank you in advance for any solutions, insights, or optimizations!
Update
Thanks to help from gniourf-gniourf, I have revised my command. This seems to do what I wanted:
find . -type f \( \! -name ".*" \! -name config.codekit \! -path "./.*" \! -path "./node_modules/*" -o -name .gitignore \)
A quick example first: to find all files, pruning the .git directories and ignoring the .DS_Store files:
find . -name .git -type d \! -prune -o \! -name .DS_Store -type f
For example, I want to exclude from my results entire directories like .git, .idea, and node_modules as well as files like .DS_Store and config.codekit, but I want to include .gitignore.
find . \( -name .git -o -name .idea -o -name node_modules \) -type d \! -prune -o \! -name .DS_Store \! -name config.codekit -type f
When building your command, make sure you stick with the POSIX standard: it's a guarantee that your command will work on any (POSIX compliant) system. For example, -not is not POSIX compliant: use ! instead (you'll have to escape it so as to not clash with your shell history expansion).
Is there a way to specify exceptions to exclusions in the find command via Bash—to say something like exclude all the things that match this pattern EXCEPT this thing or these things?
Find files, excluding everything (pattern *) except the files one and two:
find . \( \! -name '*' -o -name one -o -name two \) -type f

Recursively recode all project files excluding some directories and preserving permissions

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.

Resources