1

I'm trying out process substitution and this is just a fun exercise.

I want to append the string "XXX" to all the values of 'ls':

paste -d ' ' <(ls -1) <(echo "XXX")

How come this does not work? XXX is not appended. However if I want to append the file name to itself such as

paste -d ' ' <(ls -1) <(ls -1)

it works.

I do not understand the behavior. Both echo and ls -1 write to stdout but echo's output isn't read by paste.

Paolo
  • 1,557
  • 3
  • 18
  • 28

6 Answers6

4

Try doing this, using a printf hack to display the file with zero length output and XXX appended.

paste -d ' ' <(ls -1) <(printf "%.0sXXX\n" *  )

Demo :

$ ls -1
filename1
filename10
filename2
filename3
filename4
filename5
filename6
filename7
filename8
filename9

Output :

filename1 XXX
filename10 XXX
filename2 XXX
filename3 XXX
filename4 XXX
filename5 XXX
filename6 XXX
filename7 XXX
filename8 XXX
filename9 XXX

If you just want to append XXX, this one will be simpler :

printf "%sXXX\n" 
Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
1

If you want the XXX after every line of ls -l output, you need a second command that output x times the string. You are echoing it just once and therefore it will get appended to the first line of ls output only.

If you are searching for a tiny command line to achieve the task you may use sed:

ls -l | sed -n 's/\(^.*\)$/\1 XXX/p'
hek2mgl
  • 152,036
  • 28
  • 249
  • 266
1

And here's a funny one, not using any external command except the legendary yes command!

while read -u 4 head && read -u 5 tail ; do echo "$head $tail"; done 4< <(ls -1) 5< <(yes XXX)

(I'm only posting this because it's funny and it's actually not 100% off topic since it uses file descriptors and process substitutions)

gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
1

... you have to:

for i in $( ls -1 ); do echo "$i XXXX"; done

Never use for i in $(command). See this answer for more details.

So, to answer of this original question, you could simply use something like this :

for file in *; do echo "$file XXXX"; done

Another solution with awk :

ls -1|awk '{print $0" XXXX"}'
awk '{print $0" XXXX"}' <(ls -1) # with process substitution

Another solution with sed :

ls -1|sed "s/\(.*\)/\1 XXXX/g"
sed "s/\(.*\)/\1 XXXX/g" <(ls -1) # with process substitution

And useless solutions, just for fun :

while read; do echo "$REPLY XXXX"; done <<< "$(ls -1)"
ls -1|while read; do echo "$REPLY XXXX"; done
Community
  • 1
  • 1
Idriss Neumann
  • 3,760
  • 2
  • 23
  • 32
0

It does it only for the first line, since it groups the first line from parameter 1 with the first line from parameter 2:

paste -d ' ' <(ls -1) <(echo "XXX")

... outputs:

/dir/file-a XXXX
/dir/file-b
/dir/file-c

... you have to:

for i in $( ls -1 ); do echo "$i XXXX"; done
nsx
  • 697
  • 1
  • 13
  • 41
  • If you want to use paste, you will need an array of as many elements initialized to "XXX", as files exist in the directory that you are listing. I think it is much simpler (even some may say than less elegant) to use a for iteration as in my answer above. – nsx Oct 28 '13 at 18:56
  • 1
    Never use `for i in $(command)` See this answer for more details : http://stackoverflow.com/questions/19606864/ffmpeg-in-a-bash-pipe/19607361#19607361 – Idriss Neumann Oct 28 '13 at 20:49
0

You can use xargs for the same effect:

ls -1 | xargs -I{} echo {} XXX
perreal
  • 94,503
  • 21
  • 155
  • 181