1

Hello stackoverflow community, I'm facing a problem with removing files that contain spaces in filename, i have this part of code which is responsible of deleting files that we get from a directory,

for f in $(find $REP -type f -name "$Filtre" -mtime +${DelAvtPurge}) do rm -f $f 

I know that simple or double quotes are working for deleting files with spaces, it works for me when i try them in a command line, but when i put them in $f in the file it doesn't work at all. Could anybody help me to find a solution for this ?

2 Answers 2

1

GNU find has -delete for that:

find "$REP" -type f -name "$Filtre" -mtime +"$DelAvtPurge" -delete 

With any other find implementation, you can use bulk-exec:

find "$REP" -type f -name "$Filtre" -mtime +"$DelAvtPurge" -exec rm -f {} + 

For a dry-run, drop -delete from the first and see the list of files to be deleted; for second, insert echo before rm.

Sign up to request clarification or add additional context in comments.

11 Comments

the problem is not in Find command, the problem is in the line rm -f $f, the rest of the code if this function is like this :
for f in "$(find $REP -type f -name "$Filtre" -mtime +${DelAvtPurge})" do rm -f $f if [ $? = 0 ] then FctMsg "${CODE_ERR_OK}" "${FIC_TRC}" "Purge OK pour le fichier ${f}" else FctMsg "${CODE_ERR_WAR}" "${FIC_TRC}" "Probleme pour purger le fichier ${f}" fi done
@amy You can do all of that with find as well, I just showed how to delete files with find. Parsing find's output is not a good idea at all btw, it's an anti-pattern best way to put it
if i add the -delete option, will i have to remove the line of rm and the ' if ... else' lines ?
Why parsing find's output is not a good idea ? can you give me more explanations if you can please ?
|
0

The other answer has shown how to do this properly. But fundamentally the issue in your command is the lack of quoting, due to the way the shell expands variables:

rm -f $f 

needs to become

rm -f "$f" 

In fact, always quoting your variables is safe and generally a good idea.

However, this will not fix your code. Now filenames with spaces will work, but filenames with other valid characters (to wit, newlines) won’t. Try it:

touch foo$'\n'bar for f in $(find . -maxdepth 1 -name foo\*); do echo "rm -f $f"; done 

Output:

rm -f ./foo rm -f bar 

Clearly that won’t do. In fact, you mustn’t parse the output of find, for this reason. The only way of making this safe, apart from the solution via find -exec is to use the -print0 option:

find "$REP" -type f -name "$Filtre" -mtime +"$DelAvtPurge" -print0 \ | IFS= while read -r -d '' f; do rm -f "$f" done 

Using -print0 instead of (implicit) -print causes find to delimit hits by the null character instead of newline. Correspondingly, IFS= read -r -d '' reads a null-character delimited input string, which we do in a loop using while (the -r option prevents read from interpreting backslashes as escape sequences).

6 Comments

Thank you @Konrad, would you please tell me what does this option -print0 | read -r -d '' f do ?
@amyhart It delimits the output items of find by the zero character instead of by newlines. This is guaranteed to work because zero characters are invalid in file names (whereas newlines are!). Check out the find man page, and the Bash Pitfalls page for more details.
i will try this solution and tell you the results, thank u for your answer
@amyhart Whoops, I just noticed I had missed a word from my code. Fixed now.
i've tried and it doesn't work too, i think the problem is right here IFS= while read -r -d '' f; do , this line is not written properly, there's already a for loop before find
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.