2

I'm trying to pipe a string with special characters (e.g. HG@eg3,l'{TT\"C! to another command (termux-clipboard-set) with the read program. It seems that read was designed to create a temporary variable (e.g. read temp) that should be then passed to another command (e.g. termux-clipboard-set $temp).

I'm wondering if there is a faster way to do it with a pipe, like: read | termux-clipboard-set?

UPDATE: Sorry, I forgot to mention that I'm looking for something that would work on bash (termux).

4
  • 1
    Why do you want to use read here? Also, what shell are you using and what operating system? Does your shell support something like termux-clipboard-set <<<"HG@eg3,l'{TT\"C!"? Commented Nov 5, 2023 at 11:16
  • 1. Thanks, I've updated the tag to bash. I didn't expect it to play such a big role. 2. Because this string is usually much longer (I've truncated it in the example) and you'd need to manually go and escape every quote and other special characters. Commented Nov 5, 2023 at 11:22
  • 2
    Then please mention this in your question. Basically, please explain what you want to achieve rather than focusing on the method you think might achieve it. This is what is known as the xy probem. read isn't the right tool here, so focusing on how to force read to work is distracting from the basic question which seems to be "how can I pass a long string with special characters to the termux-clipboard-set command?". Commented Nov 5, 2023 at 11:24
  • Where does your string with special characters come from? Are you reading it from a file, or is it the output of some command? Anyway, I think you don't want to use read or a pipe. I have several rules for using bash, and one is keep things simple and go one step at a time, and another is don't use read except for user interaction. Commented Nov 6, 2023 at 16:42

2 Answers 2

10

For bash, read is not a program. read is a builtin. Simplified, read reads stdin and assigns that input to a variable. The read builtin does not produce any output on stdout, so trying to pipe stdout to something does not produce anything.

The question is why. According to the man page,

Usage termux-clipboard-set [text]

Text is read either from standard input or from command line arguments.

If text is read from stdin, why would you want to put something in front? Sure, you could cat | termux-clipboard-set, but just termux-clipboard-set would do the trick.

4
  • Oh, that explains why I couldn't redirect the output. I thought it was a regular program. Are there perhaps any alternatives that behave similarly but could be redirected? Commented Nov 5, 2023 at 11:25
  • 5
    @DanielKrajnik you can redirect the output of shell builtins just fine. You cannot redirect the output of read because it has no output, not because it is a builtin. echo is also a builtin on most shells but its output can be redirected just fine. Commented Nov 5, 2023 at 11:26
  • thanks, I misunderstood it then. You are right in the last paragraph cat | termux-clipboard-set works (I couldn't find which key terminates cat - found out eventually that CTRL+D works). I don't think that just termux-clipboard-set works anymore (this issue also mentions that it just hangs after pressing CTRL+D) Commented Nov 5, 2023 at 11:34
  • 1
    cat does nothing but copy bytes from its input to its output. So cat | termux-clipboard-set and termux-clipboard-set should behave 100% identically. If you're really finding that they're not, that's probably a quite subtle bug. Commented Nov 5, 2023 at 22:25
4

In zsh, where the read builtin supports a -e option for echo:

termux-clipboard-set "$(IFS= read -re)"

If your system still has a line command (there's still one in util-linux but it's generally not included these days), with any POSIX-like shell:

termux-clipboard-set "$(line)"

That line command could be written as a sh function as:

line() (
  IFS= read -r line; ret=$?
  printf '%s\n' "$line"
  exit "$ret"
)

head -n 1 does something similar except that when not reading from a terminal most implementations would read by blocks¹ and then may read more than a line from their input even if they output only one line. read and line are guaranteed not to (though you need to make sure to use the -r option for read).

With input coming from a terminal,

termux-clipboard-set "$(head -n1)"

Should work though. Most head implementations still also support the obsolete (but shorter) head -1.

With tcsh, that's:

termux-clipboard-set $<:q

¹ they also read by blocks from terminal devices, but read()s on terminal devices in icanon mode don't return more than one line.

3
  • What is line? On my system it seems to be part of the mesa-demos package and running opens a window with a blue background and a triangle, while the terminal shows me the values of some GL_* variables. Commented Nov 5, 2023 at 11:20
  • Thank you, unfortunately this time zsh isn't available :( (runs on termux android phone uses bash). Commented Nov 5, 2023 at 11:21
  • @terdon, line used to be a standard command up to SUSv2, removed thereafter and from many systems. Commented Nov 5, 2023 at 11:22

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.