Madan
Madan

Reputation: 45

Largest file in the system and move it in unix

I am new to bash and im struggling with it. I have an assignment which the question is

Try to find that top 5 larger files in the entire file system ordered by size and move the file to /tmp folder and rename the file with current datetime format

I tried with the following code

du -a /sample/ | sort -n -r | head -n 5

Im getting the list, but i cannot able to move..

Suggestions please

Upvotes: 0

Views: 174

Answers (1)

KamilCuk
KamilCuk

Reputation: 141145

Looks like a simple case of xargs:

du -a /sample/ | sort -n -r | head -n 5 | xargs -I{} mv {} /tmp

xargs here simply reads lines from standard input and appends them as arguments to the command, mv in this case. Because the -I{} is specified, the {} string is replaced for the argument by xargs. So mv {} /tmp is executed as mv <the first file> /tmp and mv <the second file> /tmp and so on. You can ex. add -t option to xargs or ex. add echo to see what's happenning: xargs -I{} -t echo mv {} /tmp.

Instead of running 5 processes, we could add /tmp on the end of the stream and run only one mv command:

{ du -a /sample/ | sort -n -r | head -n 5; echo /tmp; } | xargs mv

or like:

du -a . | sort -n -r | head -n 5 | { tee; echo /tmp; } | xargs mv

Note that using du -a will most probably not work with filenames with special characters, spaces, tabs and newlines. It will also include directories in it's output. If you want to filter the files only, move to much safer find:

find /sample/ -type f -printf '%s\t%p\n' | sort -n -r | cut -f2- | head -n5 | xargs -I{} mv {} /tmp

First we print each filename with it's size in bytes. Then we numerically sort the stream. Then we remove the size, ie. cut the stream on first '\t' tabulation. Then we get the head -n5 lines. Lastly, we copy with xargs. It will work for filenames not having special characters in filenames, like unreadable bytes, spaces, newlines and tabs.

For such corner cases it's preferred to use find and handle zero terminated strings, like this (note simply just -z and -0 options added):

find /sample/ -type f -printf '%s\t%p\0' | sort -z -n -r | cut -z -f2- | head -z -n5 | xargs -0 -I{} mv {} /tmp

Upvotes: 1

Related Questions