2

I am looking to combine all files in a directory (each having one column) into a single file with multiple columns. However, I need the files to be pasted by last modification time order, i.e. in the new file, the first column will come from the oldest file and the last column from the newest file.

I cannot change the names of the original files to reflect this time order. I have used the command raised and answered in this question but it doesn't quite do what I need because '*' is not intelligent to file time ordering.

paste * | column -s $'\t' -t > output.txt
thanasisp
  • 8,122
MSR
  • 21

3 Answers3

3

In the zsh shell, the gobbing qualifier om sorts the entries that a filename globbing pattern expands to in mtime timestamp order (most recently modified files first; use O in place of o to sort in the opposite order). The globbing qualifier . (a dot) would restrict the matching of the globbing pattern to only regular files.

Thus, the globbing pattern *(.om) would expand to the visible names of regular files in the current directory, sorted by the mtime timestamp.

From the bash shell:

zsh -c 'paste ./*(.om)' | column -s $'\t' -t >output.txt

By default, if the pattern does not match anything, this is treated as an error by the zsh shell (as if the failglob shell option was set in the bash shell).

Note that you may want to write the output.txt file to some other directory, or be more specific in the globbing pattern used, as to not pick up the output file name. The following would explicitly be avoiding the output.txt name with a modified globbing pattern:

zsh -o extended_glob -c 'paste ./(^output.txt)(.om)' | columns -s $'\t' -t >output.txt
Kusalananda
  • 333,661
3

To sort filenames by last-modified time:

stat -c '%Y %n' * | sort -n | cut -d " " -f 2-

This doesn't handle filenames containing newline characters.

So:

# read the sorted filenames into an array
mapfile -t files < <(stat -c '%Y %n' * | sort -n | cut -d " " -f 2-)

then paste the files together

paste "${files[@]}" | ...

glenn jackman
  • 85,964
  • 2
    Recent versions of GNU Coreutils stat have a --printf that allows null termination, and recent versions of bash mapfile can read null delimited input - so you could make it handle files with newlines in that case, as mapfile -d '' -t files < <(stat --printf '%Y\t%n\0' * | sort -zn | cut -z -f 2-) for example on suitably recent GNU-based systems – steeldriver Nov 04 '20 at 14:02
2

You can order the list of files passed to paste first:

paste $(ls -t) | column -s $'\t' -t

ls -t will return the files sorted "by modification time, newest first"

paste simply parses the files in the order specified on the command line.

Bram
  • 2,459