10

I want to find out the type of several commands. Is it possible to pipe or xargs a search result from find into the type command in Linux?

For example:

find . -name anacron | type

or

find . -name anacron | xargs type
1
  • I think that Oli answer is the best answer. Chaos answer just works, but Oli answer is clever.
    – 0x2b3bfa0
    May 19, 2015 at 10:57

2 Answers 2

17

type is not a normal command. It's a shell buitin. See:

$ type type
type is a shell builtin

So, you need to invoke bash with -c to achieve what you want

$ find . -name anacron | xargs -I '{}'  bash -c "type {}"

Or even simpler (no need for xargs):

$ find . -name anacron -exec bash -c "type {}"  \;

It will call bash -c "type ./file", with every file that is found by find. -I in xargs means, we define here a placeholder {} to use later. This placeholder is replaced with the filename found.

Why shell builtins don't work with xargs:

[...] Builtin commands are contained within the shell itself. When the name of a builtin command is used as the first word of a simple command, the shell executes the command directly, without invoking another program. [...]


xargs reads items from the standard input, [...], and executes the command

The command in this case is a simple excutable, and a shell builtin is not an executable. It cannot be found in the filesystem. It's within the shell itself. So you have to call the shell and tell the called shell to invoke the builtin command. That's what happend with bash -c "command".

2
  • 3
    You could condense it to find ... -exec bash -c 'type "$@"' _ {} +
    – muru
    May 19, 2015 at 10:22
  • 2
    @muru indeed, I read my own answer again and saw it =)
    – chaos
    May 19, 2015 at 10:24
11

There are a few problems here (some already highlighted):

  • type is a builtin. It's not a command that's resolved, it's a function inside bash. See man bash-builtins. It only works in the context of bash so not an xargs or -exec forked subshell.
  • type is used to doing its own path searching. If you give it a path (as find is wont to do), it'll probably just return that path. readlink -f might be better if you're just trying to resolve symlinks; and you can pipe into xargs readlink or -exec readlink -f {} + all day long.

That's not to say you can't do what you're trying to. There are two options. The type command can handle many names at once so you could just provide it all the names at once:

type $(find /usr/sbin -name anacron)

For many commands, if there are too many arguments you'll exceed the command line length limit (see getconf ARG_MAX). However, that won't apply in this case since type is built into the shell and doesn't generate a new process ID (the length limit applies to the exec() function used by the child process in a normal command line).

1
  • 1
    Thank you Oli! This linux newbie has learned something new today regarding about "type" and its behaviors.
    – LjinKazama
    May 19, 2015 at 10:30

You must log in to answer this question.

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