0

I intent to copy the output from ls

gaowei@alpha:~/Downloads$ ls | head -n 10 | tail -n 5
Abraham Silberschatz, Greg Gagne, Peter B. Galvin - Operating System Concepts (2018, Wiley).pdf
Alan Shalloway - Design Patterns Explained_ A New Perspective on Object-Oriented Design (2004, Addison-Wesley Professional).pdf
Alan Shalloway, James R. Trott - Design patterns explained a new perspective on object-oriented design (2004, Addison-Wesley Professional).chm
Alfred V. Aho, Monica S. Lam, Ravi Sethi, Jeffrey D. Ullman - Compilers - Principles, Techniques, and Tools (2006, Pearson_Addison Wesley).pdf
Anany Levitin - Introduction to the Design and Analysis of Algorithms (2012, Pearson).pdf

and tried

me@host:~/Downloads$ ls | head -n 10 | tail -n 5 | xargs xclip -sel clip
xclip: Abraham: No such file or directory
me@host:~/Downloads$ xclip -sel clip $(ls | head -n 10 | tail -n 5)
xclip: Abraham: No such file or directory

They failed. Should I have to redirect the output to a file before employ 'xclip'?

Alice
  • 1,710

2 Answers2

1

To pass the filenames from your pipe to xclip, all you need is

ls | head -n 10 | tail -n 5 | xclip -sel clip

because xclip by default reads text from standard input.


By adding xargs, you were passing the output of the pipe as a sequence of filename arguments to xclip, which in principle would be the way to copy the files' contents to the clipboard, however it was failing because by default xargs considers each whitespace-delimited word as a separate argument - if you did want to copy file contents to the clipboard, the way around that would be to tell xargs to use a newline delimiter:

ls | head -n 10 | tail -n 5 | xargs -d '\n' xclip -sel clip

or, even better (since newline is actually a legal - albeit rarely used - character in filenames), make the whole pipeline null-delimited:

printf '%s\0' * | head -zn 10 | tail -zn 5 | xargs -0 xclip -sel clip
steeldriver
  • 136,215
  • 21
  • 243
  • 336
0

What you can do, is use find to print filename using -name or -iname flag. xclip takes input via stdin, so all you have to do is to send the filename via pipe.

$ find -maxdepth 1  -type f -name 'Abraham*Operating Systems*pdf'  -printf '%P\n' | xclip -sel clip

The -name/-iname flags use simple pattern matching, and -printf with with %P format specifier will output just the filename. Note that find assumes current working directory . if no directory is specified.


As for your original command

$ ls | head -n 10 | tail -n 5 | xargs xclip -sel clip

there's a few problems with it. One is parsing ls (reading it's output via command), which is generally not recommended. The output may contain color control characters and other information. In fact there were proposals to add an option flag to ls so that it can output items separated by \0 character (this is the safe method), but that has been rejected by GNU developers for obvious reasons:

However ls is really a tool for direct consumption by a human, and in that case further processing is less useful. For futher processing, find(1) is more suited.

Another problem with your original command is xargs usage here. xclip can read input from stdin just fine, so if you want to send some text to clipboard, it is easy enough to just do something like echo foo | xclip -sel clip. If you want to copy contents of a file, then you should make that file stdin

xclip -sel clip < /etc/passwd

Copying filename in command-line can be problematic because of special characters such as tabs, newlines, spaces. Generally in command-line you'd use find. Filemanagers and GUI tools use URI form of filenames, where special characters and UTF-8 symbols are replaced with hex values. For example,

$ gio info --attributes='uri:'   文er-\ 林中鸟\ -\ 林中鳥-YY神曲-uUX0sZHQMkw.mp3 | awk '/uri:/{print $2}'
file:///home/xie/%E6%96%87er-%20%E6%9E%97%E4%B8%AD%E9%B8%9F%20-%20%E6%9E%97%E4%B8%AD%E9%B3%A5-YY%E7%A5%9E%E6%9B%B2-uUX0sZHQMkw.mp3

This can be passed to xclip and later pasted into web browser's address bar. Nautilus and File Selection dialogs don't seem to support pasting that from plain-text clipboard though.

See also

Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497