1

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 {} \;

Maybe?:

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:

${var##/*/}

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

Maybe?

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

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

0

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. – enoy Oct 30 '16 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 – enoy Oct 30 '16 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 '16 at 19:16
0

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).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.