0
➜  ~ cat .zshrc | grep xclip
alias c="xclip -selection c"
alias -g v='"$(xclip -selection c -o)"'
➜  ~ v
zsh: 没有那个文件或目录: file:///home/roach/Downloads/pure.png
➜  ~ 

The Chinese words "没有那个文件或目录" means "there is no file or directory".

I want copy a file located at /home/roach/Downloads/pure.png. After I choose it in dolphin KDE and copy(click right button of mouse, then click copy) it, is there a way to get /home/roach/Downloads/pure.png rather than file:///home/roach/Downloads/pure.png which showed above?

And what I think is use command like sed delete extra file:// chars, but didn't get the right method.

➜  ~ alias -g v='"$(xclip -selection c -o)|sed -e 's/file:\/\///'"'
➜  ~ v
zsh: 没有那个文件或目录: file:///home/roach/Downloads/pure.png|sed -e s/file:////
➜  ~ 

So, how to correct my alias -g v?

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255

2 Answers2

1

The shell itself can perform this substitution, avoiding the more expensive fork and exec of an external program. See "parameter expansion" in zshexpn(1) for details.

% x=file:///etc/passswd; print ${x#file://}
/etc/passswd

So in your case perhaps something like

% alias -g v='${$(xclip -selection c -o)#file://}'
% print -l v
/etc/passswd

Note that v is a somewhat common letter so may be unsuitable as a global alias.

You may also want to decide how things with spaces in the name are handled; the print -l will reveal the difference between:

alias -g v='${$(xclip -selection c -o)#file://}'
alias -g v='${"$(xclip -selection c -o)"#file://}'

when there are spaces in the contents of the clipboard.

thrig
  • 34,938
  • That's great! Thanks! May I ask it a little deep? When I have a dir or file with spaces, when I run command ls on termianl, it will show a single quote at beginnig and ending, like 'abc wasd'. And now after I copy 'abc wasd' to clipboard, how to make it work? I changed your answer to alias -g v='${"$(xclip -selection c -o)"//"#file://}' following https://unix.stackexchange.com/a/104887/232089. But, saddly it not worked. – roachsinai Feb 18 '19 at 02:34
  • What I want now is selected a dir and do copy in dolphin and copy a dir ls in zsh which will surrounded by single quote all works. – roachsinai Feb 18 '19 at 02:41
  • 1
    you probably want ${${(Q)"$(xclip -selection c -o)"}#file://} to remove one level of quoting – thrig Feb 18 '19 at 03:04
  • Hi, @thrig Thanks a lot! Could you please help me again how to combine it with sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' that I want to remove both leading and trailing spaces? – roachsinai Feb 18 '19 at 03:56
1

As you may know, the alias

alias -g v='"$(xclip -selection c -o)"'

means that, when you invoke v, the shell tries to execute a command named as the content of the clipboard. This is what happens in your first code snippet. However, invoking v and observing its effects is misleading because the intended use for this global alias is to be an argument to other commands.

Your sed-based solution will work if you properly use command substitution ($(...)) and quoting:

alias -g v='$(xclip -selection clipboard -o | sed '"'"'s|^file://||'"'"')'

Here, xclip pipes the content of the clipboard to sed, which removes the file:// part at its beginning (the pattern is anchored, note the ^). Avoiding / as the s command separator in the sed script makes it more readable and removes the need to escape / in the pattern.
The command substitution means that the output of the pipeline is substituted where v is invoked.

You can then use it as:

cp -- v /path/to/destination

Beware that this will make it harder to act upon a file named v in the current working directory, because the literal v will be always substituted. As a workaround, you will be able to use the relative path ./v.
(Also, consider that some programs accept non prefixed single-letter options, e.g. the perfectly legal (but non POSIX) ps v. Single-letter global aliases are just unsafe).

And, last but not least, such a global alias won't work with files whose name contains space characters, because they will be split by the shell after the alias is substituted.

Alternatively, you may avoid a global alias and define:

alias v="xclip -selection clipboard -o | sed 's|^file://||'"

which can be used as:

cp -- "$(v)" /path/to/destination

This will also work with file names with space characters.

Note, however, that:

  1. Leveraging the substitution capabilities of the shell, as explained in thrig's answer, would be more efficient.
  2. File names displayed by Dolphin and copied to the clipboard are encoded, and thus not suitable for being consumed by the shell as long as they include uncommon characters. For instance:

    touch $'file with a\nnewline'
    # Copied in Dolphin
    % echo "$(v)"
    file with a%0Anewline
    % cat "$(v)"
    cat: '/path/to/file with a%0Anewline': No such file or directory
    
fra-san
  • 10,205
  • 2
  • 22
  • 43