I have about 200 C files that I need to format to a text file like so:

shm_open.c and 198 others...

after making the files, the binaries are stored in ./aarch64/le/ along with .o and .dep.

I need to create a text file used at startup to make my image with the ~200 binaries, formatted like so, one line per binary:

/tmp/sem_post_stress = /home/.../.../.../.../aarch64/le/sem_post_stress

/tmp/dup_fdopendir = /home/.../.../.../.../aarch64/le/dup_fdopendir

/tmp/shm_open = /home/.../.../.../.../aarch64/le/shm_open

From this link: https://www.redhat.com/sysadmin/bash-scripting-loops

I know how to rename all files like: for i in $(ls *.); do but not how to add a prefix for my qemu environment "/tmp/" or the rest, = and absolute path.

I'm new to bash and never use it so I apologize if this is trivial, I have looked everywhere. Any hints or code is greatly appreciated!

  • You only need to create the text file (with the lines like so: /tmp/some = /home/..../aarch64/le/some), don't you? Or do you want to rename the files too? Nov 5, 2022 at 5:58
  • Only need to create the text file, going to leave the binary names as is
    – Milos
    Nov 5, 2022 at 6:00
  • 1
    Looping over the output of ls is a terrible idea. With Bash, consider: shopt -s nullglob; for f in *; do <something>; done. Look here to learn why.
    – Cbhihe
    Nov 5, 2022 at 6:19
  • 2
    @Cbhihe, very true. And sad to see RedHat documentation laden with so many coding bad practice most of which wouldn't even pass the shellcheck test. Nov 5, 2022 at 6:29

1 Answer 1


With zsh:

(for file (aarch64/le/*(N*)) print -r /tmp/$file:t = $file:P) > file.out


  • aarch64/le/*(N*) expands to the list of non-hidden executable regular files in aarch64/le, (N*) being glob qualifiers, Nullglob for the list to expand to nothing if there's no match, * to select executable files (mnemonic: same as the prefix ls -F uses for executable files).
  • $var:t takes the tail of a path (its basename).
  • $var:P takes the realPath of a path (its absolute, canonical, symlink free path as the realpath() standard function or realpath command does).

With GNU find and any shell (even bash, the GNU shell):

LC_ALL=C find "$PWD/aarch64/le/" -maxdepth 1 ! -name '.*' -executable -type f \
  -printf '/tmp/%f = %p\n' > file.out

Beware contrary to the zsh approach, that gives an unsorted list.

POSIXly with standard sh and utilities:

for file in aarch64/le/*; do
  if [ -x "$file" ] && [ -f "$file" ] && [ ! -L "$file" ]; then
    printf '%s\n' "/tmp/${file##*/} = $PWD/$file"
done > file.out

(also works in zsh and bash though note that in zsh (or bash if the failglob option is set), if there's no non-hidden file in aarch64/le/, you'll get an error).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .