When I type ls, i get the normal list, or when I type ls -la I get a details version with everything...
But I hate the layout of ls, it's just unintuitive for most of my use.
Is there some way I can modify (without changing the sorcecode of ls, bash scripts are okay however) ls so it's display instead of
-rwxr-xr-x 13 user group 123546 2011-01-01 11:11 filename0
-rwxr-xr-x 13 user group 123546 2011-01-01 11:11 filename1
-rwxr-xr-x 13 user group 123546 2011-01-01 11:11 filename2
drwx------ 13 user group 123546 2011-01-01 11:11 directory0
-rwxr-xr-x 13 user group 123546 2011-01-01 11:11 filename3
drwx------ 13 user group 123546 2011-01-01 11:11 directory1I can get a list more like:
DIRS
directory0 1293880260 700 user:group
directory1 1293880260 700 user:group
FILES
filename0 1293880260 751 user:group
filename1 1293880260 755 user:group
filename2 1293880260 777 user:group
filename3 1293880260 705 user:groupOr some other variation.
Meanwhile, preserving ability to use flags and other options.
8 Answers
You could write a bash script called ~/bin/ls that should override /bin/ls. remember to run chmod +x ~/bin/ls.
I've just written this which seems to do most of what you want to accomplish (including passing along extra arguments)
#!/bin/bash
DIRS="`/bin/ls --color=auto -l $@ | grep ^d`"
FILES="`/bin/ls --color=auto -l $@ | grep ^\-`"
if [ "$DIRS" ]
then echo "DIRECTORIES" echo -e "$DIRS\
"
fi
if [ "$FILES" ]
then echo "FILES" echo "$FILES\
"
fiSomebody might want to tidy that up a little or improve the output formatting, but there you go. Yours to do whatever you like with.
And here's some genuine sample output:
ls
DIRECTORIES
drwxr-xr-x 4 oli oli 4096 2010-12-16 15:40 markitup
drwxr-xr-x 7 oli oli 4096 2011-01-16 16:58 media
drwxr-xr-x 3 oli oli 4096 2010-12-16 15:41 post
drwxr-xr-x 9 oli oli 4096 2010-09-16 05:23 templates
FILES
-rw-r--r-- 1 oli oli 5361664 2010-09-06 16:32 db.db
-rw-r--r-- 1 oli oli 0 2008-12-11 09:22 __init__.py
-rwxr-xr-x 1 oli oli 542 2008-12-11 09:22 manage.py
-rw-r--r-- 1 oli oli 13 2010-03-23 18:14 settingsdev.py
-rw-r--r-- 1 oli oli 2642 2010-12-16 15:40 settings.py
-rw-r--r-- 1 oli oli 1818 2010-12-16 15:40 urls.py
-rw-r--r-- 1 oli oli 432 2010-06-22 20:54 views.pyAnd with arguments:
ls -a
DIRECTORIES
drwxr-xr-x 8 oli oli 4096 2011-01-12 00:46 .
drwxr-xr-x 19 oli oli 4096 2011-04-13 17:24 ..
drwxr-xr-x 6 oli oli 4096 2010-02-03 13:50 .bzr
drwxr-xr-x 4 oli oli 4096 2010-12-16 15:40 markitup
drwxr-xr-x 7 oli oli 4096 2011-01-16 16:58 media
drwxr-xr-x 3 oli oli 4096 2010-12-16 15:41 post
drwxr-xr-x 9 oli oli 4096 2010-09-16 05:23 templates
FILES
-rw-r--r-- 1 oli oli 65 2010-03-27 07:58 .bzrignore
-rw-r--r-- 1 oli oli 5361664 2010-09-06 16:32 db.db
-rw-r--r-- 1 oli oli 0 2008-12-11 09:22 __init__.py
-rwxr-xr-x 1 oli oli 542 2008-12-11 09:22 manage.py
-rw-r--r-- 1 oli oli 13 2010-03-23 18:14 settingsdev.py
-rw-r--r-- 1 oli oli 2642 2010-12-16 15:40 settings.py
-rw-r--r-- 1 oli oli 1818 2010-12-16 15:40 urls.py
-rw-r--r-- 1 oli oli 432 2010-06-22 20:54 views.py Here's my quick jab at it.
$ function lss { ls -l --group-directories-first --time-style +%s $@ | grep -v '^total' | awk 'BEGIN {print("DIRS")} {if (f!=1 && $1 ~ /^-/) {print "\nFILES"; f=1}; printf("%s\t%s %s %s:%s\n", $7, $6, $1, $3, $4);}'; }
$ alias ls='lss'
$ ls
DIRS
directory0 1305901476 drwxr-xr-x ak:ak
directory1 1305901476 drwxr-xr-x ak:ak
FILES
filename0 1305901484 -rw-r--r-- ak:ak
filename1 1305901484 -rw-r--r-- ak:ak
filename2 1305901484 -rw-r--r-- ak:ak
filename3 1305901484 -rw-r--r-- ak:akThe benefit of this approach is that it does not require multiple directory traversals and prints the output as it is ready. Try running this after touch filename{0..10000} as a test.
Drop the function and alias lines into ~/.bashrc to make it permanent.
Benchmarking from Oli:
oli@bert:~/Desktop$ mkdir test
oli@bert:~/Desktop$ cd test
oli@bert:~/Desktop/test$ mkdir dir{0..100000}
oli@bert:~/Desktop/test$ touch filename{0..100000}
oli@bert:~/Desktop/test$ time /bin/ls>/dev/null
real 0m0.975s
user 0m0.860s
sys 0m0.110s
oli@bert:~/Desktop/test$ time ls --group-directories-first -l >/dev/null
real 0m1.810s
user 0m1.210s
sys 0m0.580s
oli@bert:~/Desktop/test$ time lss>/dev/null # ændrük's method
real 0m2.035s
user 0m1.810s
sys 0m0.780s
oli@bert:~/Desktop/test$ time ~/bin/ls>/dev/null # Oli's method
real 0m5.496s
user 0m4.290s
sys 0m1.460s 1 ls -la | grep "^d" && ls -la | grep "^-" && ls -la | grep "^l"
Shows... directories, normal files, links in that order.
Make it an alias and you are set to go.
Found another method:
ls -l --color -h --group-directories-first
This one does directories first and colors the filenames.
In ~/.bashrc you can create an alias to this command like so:
alias ls1='ls -la | grep "^d" && ls -la | grep "^-" && ls -la | grep "^l"
Sample output:
drwxr-xr-x 5 96 2011-05-20 13:41 . drwxr-xr-x 16 xxxx uuuu 96 2010-03-05 12:34 .. drwx------ 2 xxxx uuuu 96 2009-02-13 14:31 .ssh drwxrwxr-x 2 xxxx uuuu 96 2009-12-03 13:49 .xxx drwxrwxr-x 5 xxxx uuuu 96 2010-12-06 15:51 xxxxxx -rw------- 1 xxxx uuuu 05 2011-05-20 14:12 .bash_history -rw-r--r-- 1 xxxx uuuu 20 2009-02-12 09:33 .bash_logout -rw-r--r-- 1 xxxx uuuu 29 2009-03-06 11:47 .bashrc -rw-r--r-- 1 xxxx uuuu 80 2011-05-20 13:42 fff -rw-rw-r-- 1 xxxx uuuu 03 2011-05-18 10:21 dffff
or for the second one: alias ls2=ls -l --color -h --group-directories-first
Sample output:
drwxrwxr-x 5 xxxx uuuu 4.0K 2010-12-06 15:51 ddddd -rw-r--r-- 1 xxxx uuuu 339M 2011-05-20 13:42 sssss -rw-rw-r-- 1 xxxx uuuu 4.6M 2011-05-18 10:21 dxsssss -rwxrwxr-x 1 xxxx uuuu 68 2011-02-22 15:55 5555 -rwxr--r-- 1 xxxx uuuu 20K 2010-12-06 16:11 ffffddddd will be in another color. add
-a to also include hidden files.and you created a command ls1 and ls2 to do this.
Extending the alias settings in .bashrc is my prefered way of getting more convenient 'ls' commands. I like especially the 'lf' (requires installation of 'tree').
# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias lf='tree -d -L 1' ls doesn't support much output customization.
Use
ls --group-directories-first -lto just get the dirs first.
Have a look at limo (not installed by default) for an alternative to ls that supports more output customization (but doesn't support all the options of ls)
One of the most powerful tools in Unix systems is the find command. We can use it to emulate ls output with -ls flag and search by file type with -type flag. Thus, what you see bellow is the exactly the same command , but with find searching for two different types. printf statements only tell you want it's listing first.
printf "****DIRS****\n"; find . -maxdepth 1 -type d -ls; echo "****FILES****"; find . -maxdepth 1 -type f -lsHere is sample output:
CURRENT DIR:[/home/xieerqi/bin]
$ printf "****DIRS****"; find . -maxdepth 1 -type d -ls; echo "****FILES****"; find . -maxdepth 1 -type f -ls
****DIRS****
5795516 4 drwxrwxr-x 8 xieerqi xieerqi 4096 Aug 19 16:25 .
5795514 4 drwxrwxr-x 2 xieerqi xieerqi 4096 Aug 19 15:27 ./c
5795511 4 drwxrwxr-x 2 xieerqi xieerqi 4096 Aug 19 15:27 ./python
5795153 4 drwxrwxr-x 2 xieerqi xieerqi 4096 Aug 19 15:41 ./perl
5795532 4 drwxrwxr-x 2 xieerqi xieerqi 4096 Aug 19 15:27 ./random
5795531 4 drwxrwxr-x 2 xieerqi xieerqi 4096 Aug 19 15:27 ./sh
5795141 4 drwxrwxr-x 2 xieerqi xieerqi 4096 Aug 19 15:27 ./cs2
****FILES****
5795538 4 -rw-rw-r-- 1 xieerqi xieerqi 178 Aug 19 16:25 ./somefile.txt
5795539 4 -rw-rw-r-- 1 xieerqi xieerqi 219 Aug 19 16:26 ./somefile2.txtNotice, that find lists all, the files, including the hidden files with the leading dot , for instance .bashrc.
Now, to make this command easier to access, create an alias to that in your .bashrc. I've made mine like so
alias ls2='printf "****DIRS****\n"; find . -maxdepth 1 -type d -ls; echo "****FILES****"; find . -maxdepth 1 -type f -ls 'Source bashrc with . .bashrc or exit and enter terminal. Your alias is now ready for use any time you want it.
My latest ls mod in ~/bin is:
#!/bin/bash
ACCOUNT_ID=$UID
#
#SET ACCOUNT_NAME
ACCOUNT_NAME=$( cat /etc/passwd | grep $ACCOUNT_ID | cut -d: -f1 );
ls -l -F --color -h --group-directories-first $1 |\ sed "s/$ACCOUNT_NAME/\$USER/g" | ack --passthru --color \\\$USER ;P.S. Had to name it ~/bin/myls or it'll hang in loop that never reaches the system's ls.
Sample Output:
$ sudo mkdir -vp /temp/Nother_DIR | tee -a /tmp/record
mkdir: created directory `/temp'
mkdir: created directory `/temp/Nother_DIR'
$ sudo chown -vR $USER:$USER /temp | f | tee -a /tmp/record
changed ownership of `/temp/Nother_DIR' to $USER:$USER
changed ownership of `/temp' to $USER:$USER
$ cd /temp
$ touch a b c d
$ ln -sv d e | tee -a /tmp/record
`e' -> `d'
$ ln -sv e f | tee -a /tmp/record
`f' -> `e'
$ myls | tee -a /tmp/record
total 4.0K
drwxr-xr-x 2 $USER $USER 4.0K Sep 19 00:46 Nother_DIR
-rw-r--r-- 1 $USER $USER 0 Sep 19 00:46 a
-rw-r--r-- 1 $USER $USER 0 Sep 19 00:46 b
-rw-r--r-- 1 $USER $USER 0 Sep 19 00:46 c
-rw-r--r-- 1 $USER $USER 0 Sep 19 00:46 d
lrwxrwxrwx 1 $USER $USER 1 Sep 19 00:46 e -> d
lrwxrwxrwx 1 $USER $USER 1 Sep 19 00:46 f -> e My latest ls mod in ~/bin is:
#!/bin/bash
ACCOUNT_ID=$UID
#
#SET ACCOUNT_NAME
ACCOUNT_NAME=$( cat /etc/passwd | grep $ACCOUNT_ID | cut -d: -f1 );
ls -l -F --color -h --group-directories-first $1 |\ sed "s/$ACCOUNT_NAME/\$USER/g" | ack --passthru --color \\\$USER ; Sorry about post's format. Tried to make usable via copy/paste, but maybe no go. Cheers!
P.S. Had to name it ~/bin/myls or it'll hang in loop that never reaches the system's ls.