0

What I want

Simplified command: echo "helloworld" | echo $1

  • I know, this would be possible with cat, but what if a command like echo does not take a file as input?

My actual command: ls -li init.vim | cut -d " " -f 1 | find / -inum $1

  • I know it does not work with $1 like that, this is only an example and $1 is only a placeholder.

Command substitution: find / -inum $(ls -li init.vim | cut -d " " -f 1)

  • This works fine, but I don't want it with command substitution.

Questions

  1. Does this work without any workarounds or command substitution?
  2. If it does not, what are the best ways to do this?


Thank you for your help :)

2
  • Why don't you want to use command substitution?
    – muru
    Jan 19 at 4:03
  • @muru Oh I use command substitution all the time, I just asked for learning purposes. I don't need it, I was just curious if there are more possibilities :)
    – Pixelbog
    Jan 19 at 10:26

1 Answer 1

0

Here, with several find implementations, you can just do:

find / -samefile init.vim

Which is also more correct as inode numbers are only unique per filesystem, so you also need to check the device number in addition to the inode number.

Here, where the whole output of a command minus the trailing newline characters it to be passed as one argument to a command, command substitution is the way to go, though leaving it unquoted doesn't make sense in this case:

find / -inum "$(ls -id init.vim | awk '{print $1; exit}')"

No need for -l, but we need -d to avoid problems if init.vim is of type directory. See also the ;exit so we only print the first field of the first line to handle cases where the file name contains newline characters.

Or better, check first that you're able to get the inode number

With

#! /bin/sh -
file=init.vim
inode=$(
  set -o pipefail # also care about ls exit status below
  ls -id -- "$file" | awk '{print $1; exit}'
) || exit
find / -inode "$inode"

(here, it's fine to leave it unquoted as we're not in a list context as that's a scalar variable assignment, so no split+glob happens).

The generic command to convert an input stream to a list of arguments is the xargs command (cross-arguments):

ls -id init.vim | awk '{print $1; exit}' |
  xargs -I @INODE@ find / -inum @INODE@

It's important to note that xargs will split the input (in its very own way where it does understand some form of quoting) to make up the arguments (and with -I, the splitting is done differently than without), see the man page on your system for details and the POSIX specification for what you can expect portably. In this case, the 12345<newline> output of awk will be split into one 12345 argument.

1
  • Oh wow, thank you for your detailed answer :) Sadly I don't have enough rep to vote you up. I knew already about the find -samefile command, I was just curious in general if there are other ways in bash to achieve this. Xargs was exactly what I was looking for. Thank you again for you post, I learned a lot :)
    – Pixelbog
    Jan 19 at 10:40

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