3

I wonder if it is possible to modify the ls -l command by a custom column.

For example, I would like this column to contain for each file, say, the first line of $(CustomCommand FILE).

  • I think maybe you could use a function called by the bashrc alias of ls itself – lese Sep 22 '15 at 17:58
  • Instead of modifying ls, why not introduce a script that runs ls and your custom command? You could alias ls to run this custom command. – Andy Dalton Sep 22 '15 at 18:06
4

Here's a very basic proof of concept. Not particularly robust (filenames with spaces will break it for example) but gets the idea across.

$ export CustomCommand=file
$ alias ls=/tmp/test/myls
$ ls
a  b  c  myls
$ ls -l
-rw-rw-r-- 1 steve steve   0 Sep 22 19:17 a a: empty
-rw-rw-r-- 1 steve steve   0 Sep 22 19:17 b b: empty
-rw-rw-r-- 1 steve steve   0 Sep 22 19:17 c c: empty
-rwxr-xr-x 1 steve steve 127 Sep 22 19:18 myls myls: POSIX shell script,     ASCII text executable
$ cat /tmp/test/myls
#!/bin/sh
if [ "$1" = "-l" ]
then
 shift
 ls -l $* | awk 'NF>2{ printf "%s ",$0 ; system("$CustomCommand " $NF) }'
else
 ls $*
fi
$
  • Thanks, I like your approach, what is the problem with spaces in filenames? It should only occur for ls -l, but ls -l * should work, right? – flonk Sep 23 '15 at 7:40
  • I used your solution and extended it, such that I can also define the CustomCommand as the first argument, i.e. in your case I would type myls file *. – flonk Sep 23 '15 at 10:38
  • Suppose I had a file named "Walt White" in that directory....the awk would interpret $NF as "White" and try to run "file White" and fail. – steve Sep 23 '15 at 19:11
1

Here is an approach putting together paste, sed, ls and saving it to bashrc. It has two main parts:

  • a "custom_command" here which takes arguments but merely prefixes each argument passed to it, with "YYY" and appends "ZZZ", the OP's actual CustomCommand of course would do something different
  • an alias named "ls1" that includes calling custom_command. Named it "ls1" to avoid conflict with "ls" because we still rely on "ls"

So in your ~/.bashrc, add:

custom_command ()
{
    for i; do
        echo "YYY${i}ZZZ"
    done
}

alias ls1='paste <( ls -lh | sed 1d ) <( custom_command * )'

And then . ~/.bashrc to make it effective in current terminal.

If the current directory contains 'dir1' 'file1' 'file2' and 'file 3' (to test a file with spaces), you can run the alias ls1 and see:

$ ls1
drwxr-xr-x 2 meme meme 4.0K Sep 22 14:33 dir1   YYYdir1ZZZ
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file1  YYYfile1ZZZ
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file2  YYYfile2ZZZ
-rw-r--r-- 1 meme meme   14 Sep 22 15:45 file 3 YYYfile 3ZZZ

Explanation

custom_command ()
{
    for i; do
        echo "YYY${i}ZZZ"
    done
}
  • The for i without specifying anything further, will cause for loop to use the positional parameters
  • the curly braces are necessary to distinguish the i variable, otherwise bash will misinterpret $iZZZ as a variable

Example output:

$ custom_command a b c
YYYaZZZ
YYYbZZZ
YYYcZZZ

When used with * bash expansion:

$ custom_command *
YYYdir1ZZZ
YYYfile1ZZZ
YYYfile2ZZZ
YYYfile 3ZZZ

The "ls -lh" normally will do this:

$ ls -lh
total 16K
drwxr-xr-x 2 meme meme 4.0K Sep 22 14:33 dir1
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file1
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file2
-rw-r--r-- 1 meme meme   14 Sep 22 15:45 file 3

Using sed, 1 means line 1, d for delete, to remove the first line:

$ ls -lh | sed 1d
drwxr-xr-x 2 meme meme 4.0K Sep 22 14:33 dir1
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file1
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file2
-rw-r--r-- 1 meme meme   14 Sep 22 15:45 file 3

The paste program, and process subsitution <(...) is the key to combining these otherwise separate outputs. Paste normally expects files as arguments, eg paste data1 data2. We use bash's process substitution so the output of commands will appear to paste as ordinary files it can work with, thus:

$ paste <( ls -lh | sed 1d ) <( custom_command * )
drwxr-xr-x 2 meme meme 4.0K Sep 22 14:33 dir1   YYYdir1ZZZ
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file1  YYYfile1ZZZ
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file2  YYYfile2ZZZ
-rw-r--r-- 1 meme meme   14 Sep 22 15:45 file 3 YYYfile 3ZZZ

The use of bashrc merely saves this command for convenient re-use in new terminals, or existing terminals where you run . ~/.bashrc to reload bash.

  • I like this approach, unfortunately ls1 looses the ability to have file arguments but only works with all files (custom_command *). – flonk Sep 23 '15 at 4:16

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.