Finding return chars in unix filenames - linux

This is part of a bigger problem but, of course, it's the bit that's giving me the most trouble. So there's something going on with our users where they're creating files with return characters by doing something like this:
touch "tpseports
old"
That's another problem and not for me to mess with. What I'm trying to do is find files like that with our script to remove outdated files. Right now, we run a find command to place the old file names into a temp file and then remove based off of that list. Something like this here:
find /home/userid \( -type f -a -mtime +365 \) 1>> TEMP
while read FILELIST
do
rm -f $FILELIST
done < TEMP
The problem is when we come across a file like:
/home/userid/tpseports
old
Because it will try to remove "/home/userid/tpseports" AND "old".
Has anybody run into something like this before and know the solution? I'm still searching around the web for ideas so if I find a solution I'll post it here.
Cheers

find has the -print0 option for cases like this:
find -type f -mtime +365 -print0 | xargs -0 rm -f

Related

`find` command core dumps in directory with too many files

I have a folder that contains so many files/folders inside it that even basic commands like du and find are crashing. I'd like to clean up some old files from it... but obviously I can't do that with the find command...
# find /opt/graphite/storage/whisper -mtime +30 -type f -delete
Aborted (core dumped)
What command or trick can I use to delete files from that folder since find isn't working?
I believe the best way to go is using a simple for-loop: the problem is that find loads all found information in memory, and only once this is done, it starts deleting.
However, a loop can solve this:
for f in $(ls -a)
do
if <check_last_modification_date>($f)
then rm -r $f
fi
done
Concerning the last modification date check, there are plenty of ways to do this, as explained here.
For find command using the -exec option worked for me to delete the files.
# find /opt/graphite/storage/whisper -mtime +30 -type f -exec rm -f {} \;

Find creates a file when I use {}

I try to use find to create a very simple way to add newline to a file. I know there are tons of other ways to do this but it bugs the hell out of me that I cannot get this way to work.
So - I'm NOT asking how to add newline to a file - I'm asking why find is weird.
find . -type f -iname 'file' -exec echo >> {} \;
results in a new file created named "{}" with the newline in while (to check that find works on my computer):
find . -type f -iname 'file' -exec echo {} \;
prints "./file".
So the >> makes find confused. The question is why and how do I solve that?
I'm asking why find is weird.
It isn't. This has nothing to do with find. In fact, when the file is created, find hasn't even started to run.
>> roughly means "redirect stdout to the end of this file, create a new file when necessary". Note how nothing of this has anything to do with whatever is left of the >>.
Redirection is a feature of the shell, find knows nothing about the redirection and the shell knows nothing about find. >> doesn't magically change its meaning just because you happened to call find. It still means the exact same thing.
If you want to use a shell feature whithin -exec, you need to use a shell within -exec:
find . -type f -iname 'file' -exec sh -c 'echo >> "{}"' \;
While the question itself has already been answered, I'd like to point out that you don't strictly need to make find do everything, rather you can use other available facilities to work together with it, for example:
find . -type f -iname 'file' | while read file; do echo >>"$file"; done
This approach also has the advantage of not executing a new process for every match, which is irrelevant in this case but potentially important if there are thousands of matches and the exec is relatively heavy.

Customized deleting files from a folder

I have a folder where different files can be located. I would like to check if it contains other files than .gitkeep and delete them, keeping .gitkeep at once. How can I do this ? (I'm a newbie when it comes to bash)
As always, there are multiple ways to do this, I am just sharing what little I know of linux :
1)find <path-to-the-folder> -maxdepth 1 -type f ! -iname '\.gitkeep' -delete
maxdepth of 1 specifies to search only the current directory. If you remove maxdepth, it will recursively find all files other than '.gitkeep' in all directories under your path. You can increase maxdepth to however deep you want find to go into directories from your path.
'-type f' specifies that we are just looking for files . If you want to find directories as well (or links, other types ) then you can omit this option.
-iname '.gitkeep' specifies a case insensitive math for '.gitkeep', the '\' is used for escaping the '.', since in bash, '.' is a regular expression.
You can leave it to be -name instead of -iname for case sensitive match.
The '!' before -iname, is to do an inverse match, i.e to find all files that don't have the name '.gitkeep', if you remove the '!', then you will get all files that match '.gitkeep'.
finally, '-delete' will delete the files that match this specification.
If you want to see what all files will be deleted before executing -delete, you can remove that flag and it will show you all the files :
find <path-to-the-folder> -maxdepth 1 -type f ! -iname '\.gitkeep'
(you can also use -print at the end, which is just redundant)
2) for i in `ls -a | grep -v '\.gitkeep'` ; do rm -rf $i ; done
Not really recommended to do it this way, since rm -rf is always a bad idea (IMO). You can change that to rm -f (to ensure it just works on file and not directories).
To be on the safe side, it is recommended to do an echo of the file list first to see if you are ready to delete all the files shown :
for i in `ls -a | grep -v '\.gitkeep'` ; do echo $i ; done
This will iterate thru all the files that don't match '.gitkeep' and delete them one by one ... not the best way I suppose to delete files
3)rm -rf $(ls -a | grep -v '\.gitkeep')
Again, careful with rm -rf, instead of rm -rf above, you can again do an echo to find out the files that will get deleted
I am sure there are more ways, but just a glimpse of the array of possibilities :)
Good Luck,
Ash
================================================================
EDIT :
=> manpages are your friend when you are trying to learn something new, if you don't understand how a command works or what options it can take and do, always lookup man for details.
ex : man find
=> I understand that you are trying to learn something out of your comfort zone, which is always commendable, but stack overflow doesn't like people asking questions without researching.
If you did research, you are expected to mention it in your question, letting people know what you have done to find answers on your own.
A simple google search or a deep dive into stack overflow questions would have provided you with a similar or even a better answer to your question. So be careful :)
Forewarned is forearmed :)
You can use find:
find /path/to/folder -maxdepth 1 ! -name .gitkeep -delete

find tekst in files in subfolders

So this question might have been asked before, but after some hours of searching (or searching wrongfully) I decided to ask this question.
If it's already been answered before, please link me the question and close this one.
here's my issue.
I have a folder on my filesystem, ie "files". this folder has got a lot of subfolders, with their subfolders. some levels deep, they all have a file which is called the same in all folders. In that file, a lot of text is in it, but it's not ALL the same. I need to have a list of files that contains a certain string.
I KNOW I can do this with
find ./ -type f -exec grep -H 'text-to-find-here' {} \;
but the main problem is: it will get over every single file on that filesystem. as the filesystem contains MILLIONS of files, this would take up a LONG time, specially when I know the exact file this piece of text should be in.
visually it looks like this:
foobar/foo/bar/file.txt
foobar/foobar/bar/file.txt
foobar/barfoo/bar/file.txt
foobar/raboof/bar/file.txt
foobar/oof/bar/file.txt
I need a specific string out of file.txt (if that string exists..)
(and yes: the file in /bar/ is ALLWAYS called file.txt...)
Can anyone help me on how to do so? i'm breaking my head on an "easy" solution :o
Thnx,
Daniel
Use the -name option to filter by name:
find . -type f -name file.txt -exec grep -H 'text-to-find-here' {} +
And if it's always in a directory named bar, you can use -path with a wildcard:
find . -type f -path '*/bar/file.txt' -exec grep -H 'text-to-find-here' {} +
With single GNU grep command:
grep -rl 'pattern' --include=*file.txt
--include=glob
Search only files whose name matches glob, using wildcard

how to delete all files with a path pattern

I have a backup location, which uses hardlinks to store existing or changed files. The location of these backups mimick the linux file system with a date part in it.
For example I have files
/backup/servername/2012-06-26T00.43.01/www.website.com/file1.html
/backup/servername/2012-06-26T06.43.01/www.website.com/file1.html
/backup/servername/2012-06-26T06.43.01/www.website.com/file2.html
/backup/servername/2012-06-26T12.43.01/www.website.com/file1.html
/backup/servername/2012-06-26T12.43.01/www.website.com/file2.html
How can I find all files which have www.website.com in them, so I can delete them
I have this command combination to delete files I can find with find, but I can't figure out how to find these files.
find . -name 'filename.*' -print0 | xargs -0 rm
You're being a little loose with your terminology, so it's a kind of tough to understand what exactly you want. However, if I understood you correctly, you want to delete all the files within a directory called www.website.com:
find . -wholename '*/www.website.com/*.html' -delete
if i understood you right you can use smth like this: find /backup/servername/2012-06-26T12.43.01/www.website.com/ -iname '*file*' -print0 | xargs -0 rm

Resources