I would like to know every file which is +100Mb and hasn't been accessed in the last month, and I have written succesfully:

find / -size +100M -atime +30

And now I want to move those files to a folder called /big-not-used changing its name as: file_nameYYYYMMDD where file_name is the orginal's file's name and YYYYMMDD is today's date, in year month day. For example film.mkv goes to /big-not-used/film.mkv20161031

My sentence would be:

find / -size +100M -atime +30 -exec mv {} /big-not-used/... \;

But I don't know how to append today's date at the file's name. I have found that date +%Y-%m-%d outputs: 2016-10-31 which is useful. Now the doubt is how to get this file's name? Following: https://stackoverflow.com/questions/5456120/how-to-only-get-file-name-with-linux-find

... -exec basename {} \;


find / -size +100M -atime +30 -exec mv {} /big-not-used/$(basename {})$(date +%Y-%m-%d) \;

But it gives an error because basename is replying with the file's full path instead of its name which I would use:


to get the file's name, but the question is how do I insert what basename {} replies into the var in the previous expresion!?.


$(${$(basename {})##/*/})

But is says sintactic error near the unexpected '}'...

2 Answers 2


You were getting close with:

find / -size +100M -atime +30 \
  -exec mv {} /big-not-used/$(basename {})$(date +%Y-%m-%d) \;

But without quoting, the shell expantion of $(...) constructs happens before the find command executes. In other words, given the above command line, which actually gets executed is:

find / -size +100M -atime +30 \
  -exec mv {} /big-not-used/{}2016-10-30 \;

Because the result of $(basename {}) is just {}, and that's why you end up with the full pathname. Try this instead:

find / -size +100M -atime +30 \
  -exec sh -c 'mv {} /tmp/big-not-used/$(basename {})$(date +%Y-%m-%d)' \;

For testing things out, you can replace mv with echo mv, like this:

find / -size +100M -atime +30 \
  -exec sh -c 'echo mv {} /tmp/big-not-used/$(basename {})$(date +%Y-%m-%d)' \;

...and see what the generated commands look like.

  • Executing it gives it an output like: mv: cannot move "read.sh" to /tmp/big-not-used/read.sh2016-31-10 the file or directory doesn't exist.
    – Yone
    Oct 30, 2016 at 15:02
  • I tried find / -size +100M -atime +30 -exec sh -c 'mkdir /big-not-used/$(basename{})$(date +%Y-%m-%d); mv {} /big-not-used/$(basename {})$(date +%Y-%m-%d)' \; Unfortunately it outputs: mkdir: cannot create directory «/big-not-used/2016-10-30»: Doesn't exist file or direcotry mv: cannot move «.» a «/big-not-used/.2016-10-30»: doesn't exist file or directory
    – Yone
    Oct 30, 2016 at 15:12
  • If that's the actual command you used, you're missing a space between basename and {}. The command as I wrote it actually works on my system (although I replace mv with cp because I don't actually want to move anything).
    – larsks
    Oct 30, 2016 at 19:16

I improved lark's solution a bit to make only a single sh call:

find / -size +100M -atime +30 -exec sh -c \
  'for f do mv "$f" /tmp/big-not-used/"$(basename "$f")$(date +%Y-%m-%d)"; done' sh {} +

Alternatively, without any sh calls at all:

while IFS= read -r f; do
  mv "$f" /tmp/big-not-used/"$(basename "$f")$(date +%Y-%m-%d)"
done < <(find / -size +100M -atime +30)

(Latter under the assumption that the file names don't any newlines in them.)

For debugging you might want to add -v to mv (if it's supported).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .