I have some files I downloaded recently and I want to name. It is possible to do something like:
rename 's/ /_/g' $(ls -t | head -n5)
Actually, I would like to rename last downloaded 5 files.
Any idea?
I have some files I downloaded recently and I want to name. It is possible to do something like:
rename 's/ /_/g' $(ls -t | head -n5)
Actually, I would like to rename last downloaded 5 files.
Any idea?
First, I have to note, parsing
ls
is generally not recommended. Its output is meant for human consumption, and this solution will fail for some legitimate file names (like those which contain newline characters, for example)With that said, the simplest solution does seem to be using
ls
(asfind
does not offer a sort-by-modification-date option). For this, you can use pipes and thexargs
command to execute the final rename.In short:
This uses your original command almost exactly, but with
xargs
to do the final completion.xargs
will take in a number of newline-separated arguments, and pass them all to a singlerename
command.Caveats
This should work - but parsing
ls
is fragile. This breaks for file names which contain the newline character; using a command that's meant for parsing likefind
would be much better.However, I don't know how to sort by last modification date with
find
. If someone else knows how to do this, you'd probably end up with something like:If
<???>
were a valid argument, this command chain would tellfind
to output files in the current directory separated with a NUL character, and thensort
,head
, andxargs
would all accept this as the deliminator rather than a newline - making the whole process much more consistent. Feel free to comment or edit this if you know how to do this, and want to replace thels
answer with this bottom part.As already pointed out, parsing
ls
is fragile. It will break if your file names have any type of weirdness (spaces, newlines, control characters etc). Since you want to replace spaces with_
, your suggested approach will fail. A safe way to do this would be:stat --printf '%n/%Y\0' *
: this will print out the name (%n
) of every file or directory in the current directory followed by a slash (/
; I am using a slash since that is not allowed in a file name so can safely be used as a separator) and the file's modification time in seconds since the epoch (%Y
) and finally a NULL character (\0
).sort -rz -k 2
: this will take NULL-separated input (-z
) and sort it in reverse order (-r
) based on the value in the second/
-separated (-t'/'
) field of each line (-k 2
).head -z -n 5
: keep the first 5 (-n 5
) null-separated (-z
) lines.cut -d'/' -z -f 1
: print the 1st (-f 1
)/
-separated (-d /
) field of null-delimited (-z
) data.I just gave
ls -q
a try:Does the desired rename, even for filenames with newline or other control characters, although it gives an error:
(with perl v5.20.2)