1

I have the following directory names:

/aaa
/bbb
/ccc
/ddd

And I want to run the following command passing in the directory names with just ls:

ls | composer show drupal/MY_DIRECTORY_NAME_HERE --available | ack versions

How can I create a one line command to pass in the directory name into this composer command in a loop?

3 Answers3

2

Since you obviously want to apply the command to all of the existing sub-directories, the cleanest way to do so (avoids the issue of directory names with special characters) would be

for dir in */
do
   composer show drupal/"$dir" --available | ack versions
done

This will iterate over all non-hidden directories and symlinks to directories (due to the trailing / on the glob pattern) and execute the command on the current directory.

Note that this assumes the command accepts directory paths with trailing /. If not, a little shell string processing to strip that / will help:

for dir in */
do
   composer show drupal/"${dir%/}" --available | ack versions
done

Additional notes:

  1. Of course, writing it as one-liner is also possible:
    for dir in */; do composer show drupal/"$dir" --available | ack versions; done
    
  2. You can adapt the command to iterate over an explicit list of directory names, as in
    for dir in '/aaa' '/bbb' '/ccc'
    do
        ...
    done
    
    The quotes around the individual list items are necessary if your actual directory names contain special characters (but note that there are cases when that alone won't suffice, so the glob-based approach shown above is still the safest).
AdminBee
  • 22,803
1

What I would do:

printf '%s\n' '/aaa' '/bbb' '/ccc' |
    xargs -I{} composer show drupal/{} --available |
    ack versions

or for any dirs from current directory:

find . -type d -mindepth 1 -maxdepth 1 -print0 |
    xargs -0 -I{} composer show drupal/{} --available |
    ack versions
0

With zsh:

for dir in *(N/); do composer show drupal/$dir --available; done | ack version

The (N/) part are glob qualifiers, N for Nullglob so you don't get an error if the glob doesn't match any file, / to select files of type directory only. If you want hidden directories to also be included, add the D (for Dotglob) qualifier.

Replace / with -/ to also include symlinks to directories (like */ (which also works in other shells) does, except the expansion of */ also adds a / at the end of each file).

Here's we're running ack only once on the output of all composer commands, as we don't need to run one for each. That also means that the overall exit status of that pipeline will reflect whether version has been found at least once in any of them. If you moved | ack version inside the loop, the overall exit status would reflect whether version has been found in the last processed directory which would not be useful.