2

I have a bunch of files with a pattern like this:

{UID}-YYMMDD-HHMMSSMM-NEW.xml

Or a real example:

56959-140918-12465122-NEW.XML

I want to copy these files to another directory in date and time order contained within the filename. I also only want to apply this to filenames that match the above pattern.

Are there any tools that exist to do this? If not I imagine a script could be used, something like.

  1. Match filenames by regex
  2. match date section by regex then list by date ascending
  3. for each date match time by regex then list by time ascending add each file to global list.
  4. Once finished with organising file list copy files
blarg
  • 1,595

3 Answers3

1

If all the matching files are in the current directory (and not in any subdirectory or if the subdirectory names do not contain -), you can use for step 1 to 3:

find -regex '.*/[0-9]+-[0-9]+-[0-9]+-NEW\.XML' | sort --field-separator=- --key=2 > filelist

and for step 4:

while IFS= read -r line; do
 cp -v $line /PATH/TO/DESTFOLDER/
done < filelist

Explanation: The regexp pattern of find matches to all files with the desribed pattern. sort separates the fields by - and sorts first according to the second field (date) then according to following fields, here the third field (time). The way to process lines in a shell is described here. Each line is stored in the $line variable and copied to the destination folder. The -v option of cp displays which file is currently copied.

jofel
  • 26,758
  • Couldn't I just make it find . -regex so that directories containing - doesn't matter? – blarg Sep 18 '14 at 15:19
  • @blarg find searches by default recursively in the current directory. Problems with the sorting order can only occur if files are in subdirectories which have - in their name. The sorting is based on the relative path to the files, not only the file name. – jofel Sep 18 '14 at 16:04
1

Zsh has a glob qualifier to change the sorting of globs. Tell it to sort by the file name with the UID- prefix removed.

cp <->-<->-<->-NEW.XML(oe\''REPLY=${REPLY#*-}'\') /somewhere/else/

(Tune the pattern if you want to be precise about the number of digits — <-> matches any sequence of digits.)

Note that the order in which files are copied may or may not be observable. Most filesystems provide at least second granularity for timestamps, but copying each file probably takes a lot less than that. There is no intrinsic order of files in a directory; the first file to be copied is not necessarily the first file listed by ls -f (depending on the filesystem, it might happen often or hardly ever).

0

What I understood from your case is that you need to copy files with this pattern to corresponding folder based on the timestamp in file name.

for that you can just iterate on them, and move each file to the approprate directory:

for i in [[:digit:]]*-NEW.XML; do  dirname="${i%6:6}"; mv $i $dirname; done;

p.s the loop here will iterate only on the files matching the passed regexp.

  • AFAIU, the OP does not want to move files to directories based on the filenames of the files, but just want to copy them in a specific order (based on the timestamp) to one destination directory. – jofel Sep 18 '14 at 16:08