8

I have a large number of pictures from an old hard drive that I'm trying to organize. If I run ls -l, I notice all of these files have a creation date of 2012 or before. Ideally, I'd like to move these to my computer's second hard drive, which is not set to mount automatically. Preferably, I could do this all as a batch with some commands linked together. So far, I have ls -l | grep -i 2012 which spits out only the files with 2012 in the date provided by ls -l. Now, the trick would be cp'ing all of those files to the new directory. I'm not sure where to go next with this because each file would have to be copied. What would be my next set of commands?

10

Do not use ls. It's not recommended to use in such cases. Moreover using grep to filter according to date is not a good idea. You filename might itself contain 2012 string, even though it was not modified in 2012.

Use find command and pipe its output.

find . -newermt 20120101 -not -newermt 20130101 -print0 | xargs -0 cp -t /your/target/directory 

Here,

-newermt 20120101  ==>  File's modified date should be newer than 01 Jan 2012
-not               ==>  reverses the following condition. Hence file should be older than 01 Jan 2013
-print0 and -0     ==>  Use this options so that the command doesn't fail when filenames contain spaces 
  • 1
    Won't `-exec mv {} /your/target/directory \;' instead of '-print 0 | xargs -0 cp -t /your/target/directory' work just as good regarding problems with spaces in names? (Also, the OP wanted to move not copy) – Hagen von Eitzen May 24 '15 at 22:10
  • ^^ Yes. Both achieve the same objective. – shivams May 25 '15 at 0:41
4

If you have newer files on the old disk that you want to ignore I would go about it like this

  1. Create a temporary marker file with a modified-by date that separates files I want from those I don't
  2. Copy files older than the marker file to the new location

Here are sample commands for this, which assume you want to maintain any directory hierarchy from the old disk in the new (cpio is a copy command, similar to tar or pax):

touch -t 201201010000 /tmp/marker    # YYYYMMDDhhmm == Jan 1st, 2012
cd /path/to/old/disk
find . -type f \! -newer /tmp/marker -print0 | cpio -pmd0 /path/to/new/disk
2

I think maybe this issue is very the same as yours, you also can check this out: Create sub-directories and organize files by date

I write this new script based on that issue's first answer:

for x in *; do
  d=$(date -r "$x" +%Y)
  mkdir -p "/your/new/directory/$d"
  mv -- "$x" "/your/new/directory/$d/"
done
  1. write this script to a file named copy.sh in your old directory.

  2. replace the /your/new/directory with your new directory's path

  3. make this file executable with chmod +x copy.sh

  4. then execute this file by ./copy.sh

  • 1
    You might want to add some exception handling, so the script doesn't move itself into a 2015 directory. – G-Man May 24 '15 at 18:46
1

You probably should use a batch tool for batch operations. Doing so will usually entail reading/writing all records in a single stream rather than, for example, invoking a separate cp process for each file copied.

There is already a cpio answer written here, which, given only the options already provided you is likely what I would choose. However, the cpio format has been improved upon and folded into the standardized pax archive format since its heyday. The same is true of tar.

A strictly POSIX-pax will not likely provide any options for directly filtering archive members based on file modification times - though the standard does specify the %T list-mode format-modifier. Still, the most commonly available pax implementation that I know of - which is the BSD version maintained by mirabilos - does extend this into a directly accessible CLI-switch.

For example, to copy only all files in the tree rooted at ./ which were last modified before ccyymmddHHMM to /target/dir you could do:

pax -rwT,201301010000 ./ /target/dir

To avoid recursing into child directories you might do instead:

pax -rwdT,201301010000 ./* /target/dir

See the man page for more.

  • I guess I really ought to learn pax, but tar and cpio still stand me well. +1 – roaima May 26 '15 at 20:21
  • @roaima - strictly speaking, while there is an actual pax archive format (which is an extension to the ustar format), the POSIX-spec'd pax utility reads/writes cpio, pax, and ustar formats. Because all three archive types amount primarily just to different means of encoding the metadata for many files alongside said files' actual data into a single stream, it isn't really too much of a stretch. I once wrote shitar - which was just a few lines of shell-script for - mostly dd - taring block devs on the fly based on the POSIX spec. – mikeserv May 26 '15 at 20:50
  • I like your linked script; strangely it would have been very useful a couple of months ago for exactly that same purpose. Oh well. I might even try to stop using cpio -H ustar ... – roaima May 26 '15 at 22:33

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.