removing files with numerals in the beginning of the file name - linux

I'm working with Ubuntu recently and I have been asked to remove files with numerals at the beginning.
How do I remove ordinary files from current directory that have numerals at the first three characters?

Since nobody else bothered to post this,
rm [0-9][0-9][0-9]*

First of all: Be careful when trying out such delete commands! Try running in a directory with test files or files that are backed up well.
You could try something like this from shell:
find . -regex './[0-9]{3}.*' -exec 'rm {}' \;
For debugging, try running it without the rm-command first, listing the files that will be deleted:
find . -regex './[0-9]{3}.*'
You may have to escape the curly braces - at least I had to in FreeBSD, using zsh-shell:
find . -regex './[0-9]\{3\}.*'

How about something like
ls | egrep '^[0-9]{3}' | xargs rm
The ls lists all the files, the egrep filters the list so that it only contains filenames that start with three digits, and the xargs applies rm to each of the filenamess that egrep lets through.

Related

How do I write a command to search and remove files, even in cases where the files can't be found?

I’m using Amazon Linux with the bash shell. I want to find and remove some PDF files in a single line, so I tried
find /home/jboss/.jenkins/jobs/myco/workspace/ebook/ -name '*.pdf' | xargs rm
This works fine if there are PDF files. But if there are none, I get the error
rm: missing operand
Is there any way to write the above statement in a single line so that it will not fail, even if there are no files to remove?
This can easily be achieved using the -r flag to xargs.
I also recommend using "special character tolerant" version:
find /home/jboss/.jenkins/jobs/myco/workspace/ebook/ -name '*.pdf' -print0 | xargs -0 -r rm
Have you tried doing it all within the find command?
find /home/jboss/.jenkins/jobs/myco/workspace/ebook/ -name '*.pdf' -exec rm -f {} \;
I've always used the construct above though I believe you can also use the switch -delete which may be a bit more efficient. If you do use it remember to put -delete at the end as find is evaluated left to right as an expression.
You don't even need find, you can simply use rm, it supports basic pattern matching. Just do the following:
rm -f path/*.pdf

How to recursively delete all files in folder that dont match a given pattern

I would like to delete all files in a given folder that dont match the pattern ^transactions_[0-9]+
Let's say I have these files in the folder
file_list
transactions_010116.csv
transactions_020116.csv
transactions_check_010116.csv
transactions_check_020116.csv
I would like to delete transactions_check_010116.csv and transactions_check_020116.csv and leave the first two as they are using ^transactions_[0-9]+
I've been trying to use find something like below, but this expression deletes everything in the folder not just the files that dont match the pattern:
find /my_file_location -type f ! -regex '^transactions_[0-9]+' -delete
What i'm trying to do here is using regex find all files in folder that dont start with ^transactions_[0-9]+ and delete them.
Depending on your implementation, you could have to use option -E to allow the use of full regexes. An other problem is that -regex gives you an almost full path starting with the directory you passed.
So the correct command should be:
find -E /my_file_location ! -regex '.*/transactions_[0-9]+$' -type f -delete
But you should first issue the same with -print to be sure...
grep has -v option to grep everything not matching the provided regex:
find . | grep -v '^transactions_[0-9]+' | xargs rm -f

Linux: how to replace all instances of a string with another in all files of a single type

I want to replace for example all instances of "123" with "321" contained within all .txt files in a folder (recursively).
I thought of doing this
sed -i 's/123/321/g' | find . -name \*.txt
but before possibly screwing all my files I would like to ask if it will work.
You have the sed and the find back to front. With GNU sed and the -i option, you could use:
find . -name '*.txt' -type f -exec sed -i s/123/321/g {} +
The find finds files with extension .txt and runs the sed -i command on groups of them (that's the + at the end; it's standard in POSIX 2008, but not all versions of find necessarily support it). In this example substitution, there's no danger of misinterpretation of the s/123/321/g command so I've not enclosed it in quotes. However, for simplicity and general safety, it is probably better to enclose the sed script in single quotes whenever possible.
You could also use xargs (and again using GNU extensions -print0 to find and -0 and -r to xargs):
find . -name '*.txt' -type f -print0 | xargs -0 -r sed -i 's/123/321/g'
The -r means 'do not run if there are no arguments' (so the find doesn't find anything). The -print0 and -0 work in tandem, generating file names ending with the C null byte '\0' instead of a newline, and avoiding misinterpretation of file names containing newlines, blanks and so on.
Note that before running the script on the real data, you can and should test it. Make a dummy directory (I usually call it junk), copy some sample files into the junk directory, change directory into the junk directory, and test your script on those files. Since they're copies, there's no harm done if something goes wrong. And you can simply remove everything in the directory afterwards: rm -fr junk should never cause you anguish.

Remove all files in a directory (do not touch any folders or anything within them)

I would like to know whether rm can remove all files within a directory (but not the subfolders or files within the subfolders)?
I know some people use:
rm -f /direcname/*.*
but this assumes the filename has an extension which not all do (I want all files - with or without an extension to be removed).
Although find allows you to delete files using -exec rm {} \; you can use
find /direcname -maxdepth 1 -type f -delete
and it is faster. Using -delete implies the -depth option, which means process directory contents before directory.
find /direcname -maxdepth 1 -type f -exec rm {} \;
Explanation:
find searches for files and directories within /direcname
-maxdepth restricts it to looking for files and directories that are direct children of /direcname
-type f restricts the search to files
-exec rm {} \; runs the command rm {} for each file (after substituting the file's path in place of {}).
I would like to know whether rm can remove all files within a directory (but not the subfolders or files within the subfolders)?
That's easy:
$ rm folder/*
Without the -r, the rm command won't touch sub-directories or the files they contain. This will only remove the files in folder and not the sub-directories or their files.
You will see errors telling you that folder/foo is a directory can cannot be removed, but that's actually okay with you. If you want to eliminate these messages, just redirect STDERR:
$ rm folder/* 2> /dev/null
By the way, the exit status of the rm command may not be zero, so you can't check rm for errors. If that's important, you'll have to loop:
$ for file in *
> do
> [[ -f $file ]] && rm $file
> [[ $? -ne 0 ]] && echo "Error in removing file '$file'"
> done
This should work in BASH even if the file names have spaces in them.
You can use
find /direcname -maxdepth 1 -type f -exec rm -f {} \;
A shell solution (without the non-standard find -maxdepth) would be
for file in .* *; do
test -f "$file" && rm "$file"
done
Some shells, notably zsh and perhaps bash version 4 (but not version 3), have a syntax to do that.
With zsh you might just type
rm /dir/path/*(.)
and if you would want to remove any file whose name starts with foo, recursively in subdirectories, you could do
rm /dir/path/**/foo*(.)
the double star feature is (with IMHO better interactive completion) in my opinion enough to switch to zsh for interactive shells. YMMV
The dot in parenthesis suffix indicates that you want only files (not symlinks or directories) to be expanded by the zsh shell.
Unix isn't DOS. There is no special "extension" field in a file name. Any characters after a dot are just part of the name and are called the suffix. There can be more than one suffix, for example.tar.gz. The shell glob character * matches across the . character; it is oblivious to suffixes. So the MS-DOS *.* is just * In Unix.
Almost. * does not match files which start with a .. Objects named with a leading dot are, by convention, "hidden". They do not show up in ls either unless you specify -a.
(This means that the . and .. directory entries for "self" and "parent" are considered hidden.)
To match hidden entries also, use .*
The rm command does not remove directories (when not operated recursively with -r).
Try rm <directory> and see. Even if the directory is empty, it will refuse.
So, the way you remove all (non-hidden) files, pipes, devices, sockets and symbolic links from a directory (but leave the subdirectories alone) is in fact:
rm /path/to/directory/*
to also remove the hidden ones which start with .:
rm /path/to/directory/{*,.*}
This syntax is brace expansion. Brace expansion is not pattern matching; it is just a short-hand for generating multiple arguments, in this case:
rm /path/to/directory/* /path/to/directory/.*
this expansion takes place first first and then globbing takes place to generate the names to be deleted.
Note that various solutions posted here have various issues:
find /path/to/directory -type f -delete
# -delete is not Unix standard; GNU find extension
# without -maxdepth 1 this will recurse over all files
# -maxdepth is also a GNU extension
# -type f finds only files; so this neglects to delete symlinks, fifos, etc.
The GNU find solutions have the benefit that they work even if the number of directory entries to be deleted is huge: too large to pass in a single call to rm. Another benefit is that the built-in -delete does not have issues with passing funny path names to an external command.
The portable workaround for the problem of too many directory entries is to list the entries with ls and pipe to xargs:
( cd /path/to/directory ; ls -a | xargs rm -- )
The parentheses mean "do these commands in a sub-process"; this way the effect of the cd is forgotten, which is useful in scripting. ls -a includes the hidden files.
We now include a -- after rm which means "this is the last option; everything else is a non-option argument". This guards us against directory entries whose names are indistinguishable from options. What if a file is called -rf and ends up the first argument? Then you have rm -rf ... which will blow off subdirectories.
The easiest way to do this is to use:
rm *
In order to remove directories, you must specify the option -r
rm -r
so your directories and anything contained in them will not be removed by using
rm *
per the man page for rm, its purpose is to remove files, which is why this works

find and remove files with space using find command on Linux

I'm trying to remove all thumbs.db files in a Windows partition using find command in Ubuntu:
find . -iname "*.db"|while read junk;do rm -rfv $junk;done
But it's not working for me and nothing happens! I think I found the problem, the white spaces in directory names!
I did this trick to remove my junk files before on previous version of Ubuntu but now on latest version of Ubuntu I can't.
Is there any bug in my command?
I'd do it this way:
find . -iname 'thumbs.db' -exec rm -rfv {} +
This way, it still works even if your directories contain whitespace in their names.
just to throw this out there
find . -name "*.pyc" -delete
I'm not sure why you're using while.
find . -iname 'thumbs.db' -exec rm -rfv {} \;
...should suffice (and only delete the files you want to, not any BDB files that may be laying around).
The code looks good and works on arch and debian. Maybe there are no files matching "*.db"?
As a sidenote: I might not be a good idea to delete all files with the suffix ".db", because you can accidently delete other files than "Thumbs.db"
First check if the first part of your command, that is:
find . -iname "*.db"
is returning anything.
If it does then you can use xargs as follows to accomplish your task:
find . -iname "*.db" | xargs rm -rfv
UPDATE: From comments, this is unsafe, specially if there are spaces in directory/file names. You will need to use -print0 / xargs -0 to make it safe.

Resources