BhishanPoudel
BhishanPoudel

Reputation: 17164

How to combine a prefix to output of ls in bash?

Let's say I have some images in parent directory: ../imagea/a.png and ../images/b.png.

When I do:

ls ../images

# I get
../images/a.png
../images/b.png

How to add the prefix ![]( and the suffix ) for all these outputs?

I tried:

!ls ../images/*.png | cat

# am not sure what to do next

Required output

![](../images/a.png)
![](../images/b.png)

Help is appreciated.

Upvotes: 5

Views: 3942

Answers (4)

Dudi Boy
Dudi Boy

Reputation: 4900

The easiest solution is using the standard posix find command with printf action like this:

 find ../images -name "*.png" -printf '![](%p)\n'

Explanation:

../images - target directory

"*.png" - glob pattern

-printf - format action to output

'![](%p)\n' - format arguments to output full path name.

Example:

$ ls -l
total 8
drwxrwxr-x.  3 cfrm cfrm   15 Dec 13  2018 app
drwxrwxr-x.  2 cfrm cfrm   23 Mar 24  2019 app_5811_install
drwxrwxr-x. 13 cfrm cfrm 4096 Dec 12  2018 app_58_install
drwxrwxr-x.  2 cfrm cfrm 4096 Oct  3  2018 grants
-rwx------.  1 cfrm cfrm  526 Feb 17  2019 ic_start_all.sh
-rwx------.  1 cfrm cfrm  920 Oct  4  2018 ic_status_all.sh
-rwx------.  1 cfrm cfrm  984 Sep 27  2018 ic_stop_all.sh
-rwxrwxr-x.  1 cfrm cfrm 1693 Dec 13  2018 loadTrigger.sh



$ find . -name "*.sh" -printf '![](%p)\n'
![](./ic_stop_all.sh)
![](./ic_status_all.sh)
![](./loadTrigger.sh)
![](./ic_start_all.sh)

Upvotes: 5

dave_thompson_085
dave_thompson_085

Reputation: 38990

First, I disbelieve you. ls ../images would output only the basenames, like:

a.png
b.png
...etc...

A different command ls ../images/* could give the output you show.

Although on a system using the ls from GNU coreutils, like Linux, if the output is a terminal and the filenames are short like you showed, ls without options would do multicolumn output more like:

../images/aaaaa.png   ../images/ddddd.png  ../images/ggggg.png
../images/b.png       ../images/eeeee.png  ../images/hhhhhh.png
../images/ccccc.png   ../images/f.png      ../images/iiiiii.png

unless you have an alias (or shadowing function or script) that forces the -1 (one) option to prevent this. Or the actual names are (significantly) longer, as they probably should be. Or you are piping to something, even cat, because then the output of ls is the pipe not the terminal. These details matter.

For some cases sed is as good as awk, and usually terser:

ls | sed 's/^/![](/; s/$/)/'
# sed processes a string of command(s) for each line read from stdin, 
# and writes the result to stdout (by default, -n overrides this)
# s/old/new/ is string replacement using regex (which can be complex)
# ^ in old matches the beginning of the line
# $ in old matches the end of the line

# this assumes none of your filenames contains a newline character
# which Unix permits, but is rarely done because it is quite confusing

or since you like printf it can do the whole job:

printf '![](%s)\n' ../images/*
# printf takes a format string containing any mixture of literal text 
# (including backslash+letter escapes mostly the same as C et succ)
# and conversion specifiers beginning with % which each interpolate one argument
# it repeats the format as needed to handle all the arguments, so here 
# with one c.s. it repeats the format once for each argument = filename

# this 'works' even if a filename contains newline
# (but I don't think the result will work correctly as markdown)

Upvotes: 3

RavinderSingh13
RavinderSingh13

Reputation: 133650

Could you please try following.

awk 'BEGIN{for(i=1;i<ARGC;i++)print "![](..",ARGV[i]")"}' ../images/*.png

Output will be as follows(where a,b,c... .png are test files created by me for testing purposes).

![](.. ../images/a.png)
![](.. ../images/b.png)
![](.. ../images/c.png)
![](.. ../images/d.png)

Upvotes: 1

janos
janos

Reputation: 124724

Loop over the glob pattern, and print each line formatted as desired:

for filename in ../*.png; do echo '!'"[]($filename)"; done

Upvotes: 4

Related Questions