Currently, the use of `$in` on a stream in a pipeline results in a "collected" value, meaning the pipeline "waits" on the stream to complete before handling `$in` with the full results. However, this behavior is not guaranteed in future releases. To ensure that a stream is collected into a single variable, use the [`collect` command](/commands/docs/collect.html).
Likewise, avoid using `$in` when normal pipeline input will suffice, as internally `$in` forces a conversion from `PipelineData` to `Value` and _may_ result in decreased performance and/or increased memory usage.
## Working with External Commands
Nu commands communicate with each other using the Nu data types (see [types of data](types_of_data.md)), but what about commands outside of Nu? Let's look at some examples of working with external commands:
`internal_command | external_command`
Data will flow from the internal_command to the external_command. This data will get converted to a string, so that they can be sent to the `stdin` of the external_command.
`external_command | internal_command`
Data coming from an external command into Nu will come in as bytes that Nushell will try to automatically convert to UTF-8 text. If successful, a stream of text data will be sent to internal_command. If unsuccessful, a stream of binary data will be sent to internal command. Commands like [`lines`](/commands/docs/lines.md) help make it easier to bring in data from external commands, as it gives discrete lines of data to work with.
`external_command_1 | external_command_2`
Nu works with data piped between two external commands in the same way as other shells, like Bash would. The `stdout` of external_command_1 is connected to the `stdin` of external_command_2. This lets data flow naturally between the two commands.
### Command Input and Output Types
The Basics section above describes how commands can be combined in pipelines as input, filters, or output.
How you can use commands depends on what they offer in terms of input/output handling.
You can check what a command supports with [`help <command name>`](/commands/docs/help.md), which shows the relevant *Input/output types*.
For example, through `help first` we can see that the [`first` command](/commands/docs/first.md) supports multiple input and output types:
```nu
help first
# => […]
# => Input/output types:
# => ╭───┬───────────┬────────╮
# => │ # │ input │ output │
# => ├───┼───────────┼────────┤
# => │ 0 │ list<any> │ any │
# => │ 1 │ binary │ binary │
# => │ 2 │ range │ any │
# => ╰───┴───────────┴────────╯
[a b c] | first took 1ms
# => a
1..4 | first took 21ms
# => 1
```
As another example, the [`ls` command](/commands/docs/ls.md) supports output but not input:
```nu
help ls
# => […]
# => Input/output types:
# => ╭───┬─────────┬────────╮
# => │ # │ input │ output │
# => ├───┼─────────┼────────┤
# => │ 0 │ nothing │ table │
# => ╰───┴─────────┴────────╯
```
This means, for example, that attempting to pipe into `ls` (`echo .. | ls`) leads to unintended results.
The input stream is ignored, and `ls` defaults to listing the current directory.
To integrate a command like `ls` into a pipeline, you have to explicitly reference the input and pass it as a parameter:
```nu
echo .. | ls $in
```
Note that this only works if `$in` matches the argument type. For example, `[dir1 dir2] | ls $in` will fail with the error `can't convert list<string> to string`.
Other commands without default behavior may fail in different ways, and with explicit errors.
For example, `help sleep` tells us that [`sleep`](/commands/docs/sleep.md) supports no input and no output types:
```nu
help sleep
# => […]
# => Input/output types: