Score:6

My `find` command in script does not find files and directories with spaces in their names

pr flag

Some time ago I wrote a script that moves files and directories from Downloads to .Downloads if they are older than 3 days, and delete them from this directory after 30 days. It is working just fine, but only for files with no spaces.

I investigated and found that the find command that I use in the script is not working as I expected for any file or directory with spaces in their name.

Here is what find does:

find command output

I expected to see the find command find the files with spaces too.

Here is the script:

#! /bin/bash
# set -x
export DISPLAY=:0.0

# true - delete, else - move
function process(){
    if [ "$2" = "DELETE" ]; then
        rm -r "$1" && notify-send "$3 $1 deleted!"
    else
    mv "$1" "../.Downloads/$1" && notify-send "$3 $1 moved to ~/.Downloads/$1!"
    fi
}

# remove empty directories
for emptyDir in `find ~/Desktop/ ~/Downloads/ -empty -type d`; do
    notify-send "Directoy $emptyDir was deleted, because was empty!"
done
find ~/Desktop/ ~/Downloads/ -empty -type d -delete

# remove / move old files / directorie
if [ -z "$1" ] || [ "${1,,}" != "delete" ] && [ "${1,,}" != "move" ]; then
    echo "Give as parameter mode ( delete / move )"
    exit
fi

if [ "${1,,}" == "delete" ]; then
    day=30
    path=".Downloads"
    mode="DELETE"
else
    day=2
    path="Downloads"
    mode="MOVE"
  cr  
  if [ ! -d "~/.Downloads" ]; then
    mkdir -p ~/.Downloads
  fi
fi

cd ~/$path

for element in *
do
    if [ -d "$element" ]; then
        if [ $(find "$element" -type f -mtime -$day | wc -l) -eq 0 ]; then
            process "$element" "$mode" "Directory"
        fi
    else
        if [ $(find `pwd` -name "$element" -mtime +$day | wc -l) -gt 0 ]; then
            process "$element" "$mode" "File"
        fi
    fi
done

I would kindly ask you to tell me what I may be doing wrong.

Thanks in advance!

GammaGames avatar
in flag
You could put something as simple as `@reboot [username] find ~/Downloads/ -mtime +3 -exec gio trash {} \;` in your crontab. My distro is set to wipe trash files after 30 days, but that could also be done manually with the `trash-cli` package.
Score:13
hr flag

tl;dr: it's not the spaces, it's the brackets1

The find command's -name test uses shell glob expressions - adding quotes around the argument prevents glob special characters from being interpreted by your shell, but find still requires them to be escaped.

Ex.

$ touch 'filename with [brackets] in it'
$ find . -name 'filename with [brackets] in it'
$

(no results - because [brackets] means any single character in the set b, r, a, c, k, e, t, s); whereas

$ find . -name 'filename with \[brackets\] in it'
./filename with [brackets] in it

If you need to implement this programatically, you could perhaps use the bash shell's printf to add the required escapes:

$ element='filename with [brackets] in it'
$ find . -name "$(printf '%q' "$element")"
./filename with [brackets] in it

  1. however you WILL have an issue with whitespace in the line

    for emptyDir in `find ~/Desktop/ ~/Downloads/ -empty -type d`; do
    

    See Why is looping over find's output bad practice?

  2. there are a number of other issues, for example the quoted ~ in [ ! -d "~/.Downloads" ] will not expand to $HOME - generally you should avoid ~ in scripts

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.