-2

I need to write a script to sort filenames by the character that comes after the first "0" in the name. All the file names contain at least one 0. Then the script should print the content of each file by that order.

I know i need to use sort and cat. But i can't figure out what sort. This is as far as I've got.


#!/bin/bash

dir=$(pwd)


for n in $dir `ls | sort -u `  ; do

    cat $n
done;
kenlukas
  • 3,616
  • 9
  • 25
  • 36

4 Answers4

1

Assuming that

  1. the first zero could be anywhere in the filename,
  2. there could be several files with the same name after the zero,
  3. you want to be able to handle any filename, including dotfiles and names containing newlines, and
  4. you have GNU CoreUtils installed (standard on common distros),

you'll need to do something crazy like this (untested):

find . -mindepth 1 -maxdepth 1 -exec printf '%s\0' {} + | while IFS= read -r -d ''
do
    printf '%s\0' "${REPLY#*0}"
done | sort --unique --zero-terminated | while IFS= read -r -d ''
do
    for file in ./*"$REPLY"
    do
        […]
    done
done

Explanation:

  1. Print all filenames NUL separated and read them back in to be able to do variable substitution on them.
  2. Remove everything up to and including the first zero in the filename and print that.
  3. Sort by the remainder of the filename, making sure to only print each unique suffix once.
  4. Process each file ending with the (now sorted) suffix.
l0b0
  • 55,365
  • 30
  • 138
  • 223
0

Take a look at this find + xargs that will correctly handle filenames with "funny characters":

find . -maxdepth 1 -type f -name '*0*' -print0 | sort -zt0 -k2 | xargs -0 cat
PesaThe
  • 7,259
  • 1
  • 19
  • 43
-2

You could write a script that looks like this:

#/bin/bash

# using "shopt -s nullglob" so that an empty directory won't give you a literal '*'.
shopt -s nullglob

# get a sorted directory listing
filelist=$(for i in .*0* *0*; do echo "$i"; done | sort -t0 -k2)

IFS=$(echo -en "\n\b")
# iterate over your sorted list
for f in $filelist
do
        # just cat text files.
        file $f | grep text > /dev/null 2>&1
        if [ $? = 0 ]
        then
                cat $f
        fi
done

Test:

[plankton@localhost SO_scripts]$ ls -l
total 40
-rw-r--r-- 1 plankton plankton  10 Sep  9 10:56 afile0zzz
-rw-r--r-- 1 plankton plankton  14 Sep  9 10:56 bfile xxx0yyy
-rwxr-xr-x 1 plankton plankton 488 Sep  9 10:56 catfiles.sh
-rw-r--r-- 1 plankton plankton   9 Sep  9 10:56 file0123
-rw-r--r-- 1 plankton plankton   9 Sep  9 10:56 file0124
-rw-r--r-- 1 plankton plankton   7 Sep  9 10:56 file0a
-rw-r--r-- 1 plankton plankton   8 Sep  9 10:56 file0aa
-rw-r--r-- 1 plankton plankton   7 Sep  9 10:56 file0b
-rw-r--r-- 1 plankton plankton   9 Sep  9 10:56 file0bbb
-rw-r--r-- 1 plankton plankton  18 Sep  9 10:56 files*_0asdf
[plankton@localhost SO_scripts]$ ./catfiles.sh
. is not a text file
.. is not a text file
Doing catfiles.sh
#/bin/bash

# using "shopt -s nullglob" so that an empty directory won't give you a literal '*'.
shopt -s nullglob

# get a sorted directory listing

filelist=$(for i in .* *; do echo "$i"; done | sort -t0 -k2)

IFS=$(echo -en "\n\b")
# iterate over your sorted list
for f in $(for i in .* *; do echo "$i"; done | sort -t0 -k2)
do
        # just cat text files.
        file $f | grep text > /dev/null 2>&1
        if [ $? = 0 ]
        then
                echo "Doing $f"
                cat $f
        else
                echo "$f is not a text file"
        fi
done
Doing file0123
file0123
Doing file0124
file0124
Doing file0a
file0a
Doing file0aa
file0aa
Doing files*_0asdf
file with * in it
Doing file0b
file0b
Doing file0bbb
file0bbb
Doing bfile xxx0yyy
bfile xxx0yyy
Doing afile0zzz
afile0zzz

Updated as per PesaThe's suggestion of .*0* *0*.

Red Cricket
  • 9,762
  • 21
  • 81
  • 166
  • You commented that the accepted answer would break on whitespace. But your answer will break as well! 1) you don't quote expansions 2) you rely on word-splitting to iterate over the files `for f in $filelist` 3) and as unlikely as it is, you are not considering filenames with newlines in them. – PesaThe Sep 09 '18 at 09:15
  • I left out a line. The above should handle white space in the file names now. – Red Cricket Sep 09 '18 at 16:32
  • Hm, this is a bit better. Not sure what the `\b` is for though. It will still fail for filenames with newlines and it will be subject to pathname expansion. – PesaThe Sep 09 '18 at 17:49
  • I am not going to worry about newlines in the file names. :) Not sure what "pathname expansion" is? Can you give an example. – Red Cricket Sep 09 '18 at 17:51
  • Create a filename `*` for example and you will get crazy results :) I know newlines are unlikely, but it isn't that hard to write a code that supports them. – PesaThe Sep 09 '18 at 17:53
  • I just did a test and the script seems to handle filenames with `*` in them. I'll up my answer to show my test. – Red Cricket Sep 09 '18 at 17:58
  • Heh, you have to choose a funny filename, for example `file0*` ;) – PesaThe Sep 09 '18 at 18:08
  • I did. I think the script works for file with `*` in their names. – Red Cricket Sep 09 '18 at 18:17
  • 1
    https://repl.it/repls/FunctionalOldAddons this is your code with a little change here `for i in .*0* *0*` so that it processes only filenames with at least one `0`. There are 9 files with a `0` in their name. That's a lot of lines though! – PesaThe Sep 09 '18 at 18:25
-3
dir=$(pwd)

for n in `ls -1 $dir | sort -t0 -k2`; do
   cat $n
done;
Murli
  • 728
  • 5
  • 15
  • I don't think the `dir=$(pwd)` is necessary. Also the `ls -1 …` command will miss any files who's names start with a `.` and the `sort -t0 -k2` looks suspicious to me. And what if a file name contains whitespace? – Red Cricket Sep 09 '18 at 02:03
  • "dir=$(pwd)" is from the question posted. Since the question talks about predictable file pattern, like always contains 0 and sort after first 0, it is implied that files are generated by a controlled environment probably like an automated script. Since it is a specific problem one may not need a truly general solution! – Murli Sep 09 '18 at 02:31
  • Ah the sort does make sense. But the other issues still apply. – Red Cricket Sep 09 '18 at 02:48