moinudin
moinudin

Reputation: 138417

Pipe to/from the clipboard in a Bash script

Is it possible to pipe to/from the clipboard in Bash?

Whether it is piping to/from a device handle or using an auxiliary application, I can't find anything.

For example, if /dev/clip was a device linking to the clipboard we could do:

cat /dev/clip        # Dump the contents of the clipboard
cat foo > /dev/clip  # Dump the contents of "foo" into the clipboard

Upvotes: 1321

Views: 850882

Answers (30)

F. Hauri  - Give Up GitHub
F. Hauri - Give Up GitHub

Reputation: 70912

My tests and explanation about clipboards and xclip usage.

Introduction

From man xclip:

  -i, -in
         read text into X selection from standard input or files (default)

  -o, -out
         print the selection to standard out (generally for piping to a file or
         program)
...
  -t, -target
         specify  a particular data format using the given target atom.  With -o
         the special target atom name "TARGETS" can be used to  get  a  list  of
         valid target atoms for this selection.  For more information about tar‐
         get atoms refer to ICCCM section 2.6.2
...
  -selection
         specify  which X selection to use, options are "primary" to use XA_PRI‐
         MARY  (default),  "secondary"  for  XA_SECONDARY  or  "clipboard"   for
         XA_CLIPBOARD

There are 3 differents clipboards:

  • primary for XA_PRIMARY, they could be abbreviated p, this clipboard used for storing information copied by Ctrl+C or Ctrl+X.
  • seconday for XA_SECONDARY, they could be abbreviated s (I'm not sure where this clipboard is used) and
  • clipboard for XA_CLIPBOARD which is used immediately when some text are selected (by left mouse button or any VIM or EMACS trapping method.) and could be pasted by simple click on middle mouse button.

Dump ALL clipboard informations

Well, for showing what are precisely stored, I wrote this:

clipDump () {
    local tgts tgt clip errstr
    local -i errfd
    mapfile -t tgts < <(xclip -selection ${1:-primary} -o -t TARGETS)
    for tgt in "${tgts[@]}"; do
        exec {errfd}<> <(:)
        clip="$(xclip -selection ${1:-primary} -t $tgt -o 2>&$errfd)"
        IFS= read -ru $errfd -t .01 errstr
        exec {errfd}>&-
        printf '%-30s: %q\e[31m%q\e[0m\n' $'\e[44;30m'"$tgt"$'\e[0m' "$clip" "$errstr"
    done
}

Note: I use printf %q in order to prevent binary data to polute output. This will translate newlines into \n and so on.

Immediately after pasted this, I'v tried:

clipDump c
TIMESTAMP         : 1695759029''
TARGETS           : $'TIMESTAMP\nTARGETS\nMULTIPLE\nSAVE_TARGETS\ntext/html\ntex
t/_moz_htmlcontext\ntext/_moz_htmlinfo\nUTF8_STRING\nCOMPOUND_TEXT\nTEXT\nSTRING
\ntext/plain;charset=utf-8\ntext/plain\ntext/x-moz-url-priv'''
MULTIPLE          : ''Error:\ target\ MULTIPLE\ not\ available
SAVE_TARGETS      : ''''
text/html         : \<meta\ http-equiv=\"content-type\"\ content=\"text/html\;\ 
charset=utf-8\"\>\<pre\ class=\"lang-bash\ s-code-block\"\>\<code\ data-highligh
ted=\"yes\"\ class=\"hljs\ language-bash\"\>xclip\ -sel\ clip\ -o\ -t\ TIMESTAMP
\</code\>\</pre\>''
bash: warning: command substitution: ignored null byte in input
text/_moz_htmlcontext: \<html\ itemscope=\"\"\ itemtype=\"https://schema.org/QAP
age\"\ class=\"html__responsive\ \"\ lang=\"en\"\>\<body\ class=\"question-page\
 unified-theme\ theme-dark\"\>\<div\ class=\"container\"\>\<div\ id=\"content\"\
 class=\"snippet-hidden\"\>\<div\ itemprop=\"mainEntity\"\ itemscope=\"\"\ itemt
ype=\"https://schema.org/Question\"\>\<div\ class=\"inner-content\ clearfix\"\>\
<div\ id=\"mainbar\"\ role=\"main\"\ aria-label=\"question\ and\ answers\"\>\<di
v\ class=\"question\ js-question\"\ data-questionid=\"79058411\"\ data-position-
on-page=\"0\"\ data-score=\"0\"\ id=\"question\"\>\<div\ class=\"post-layout\ \"
\>\<div\ class=\"postcell\ post-layout--right\"\>\<div\ class=\"s-prose\ js-post
-body\"\ itemprop=\"text\"\>\<pre\ class=\"lang-bash\ s-code-block\"\>\</pre\>\<
/div\>\</div\>\</div\>\</div\>\</div\>\</div\>\</div\>\</div\>\</div\>\</body\>\
</html\>''
bash: warning: command substitution: ignored null byte in input
text/_moz_htmlinfo: 0\,0''
UTF8_STRING       : xclip\ -sel\ clip\ -o\ -t\ TIMESTAMP''
COMPOUND_TEXT     : xclip\ -sel\ clip\ -o\ -t\ TIMESTAMP''
TEXT              : xclip\ -sel\ clip\ -o\ -t\ TIMESTAMP''
STRING            : xclip\ -sel\ clip\ -o\ -t\ TIMESTAMP''
text/plain;charset=utf-8: xclip\ -sel\ clip\ -o\ -t\ TIMESTAMP''
text/plain        : xclip\ -sel\ clip\ -o\ -t\ TIMESTAMP''
bash: warning: command substitution: ignored null byte in input
text/x-moz-url-priv: https://stackoverflow.com/questions/79058411/xclip-timestam
p-time-units''

But there are some errors! can't deal with null bytes.

Dump clipboard through od:

Replacing 1st %q by '%s'and using od -A n -t a for showing null bytes.

clipDump () {
    local tgts tgt clip errstr
    local -i errfd
    mapfile -t tgts < <(xclip -selection ${1:-primary} -o -t TARGETS)
    for tgt in "${tgts[@]}"; do
        exec {errfd}<> <(:)
        clip="$(xclip -selection ${1:-primary} -t $tgt -o 2>&$errfd | od -t a -A n)"
        IFS= read -ru $errfd -t .01 errstr
        exec {errfd}>&-
        printf "%-30s: '%s'\e[31m%q\e[0m\n" $'\e[44;30m'"$tgt"$'\e[0m' "$clip" "$errstr"
    done
}
clipDump c
TIMESTAMP         : '   1   6   9   5   7   5   9   0   2   9  nl'''
TARGETS           : '   T   I   M   E   S   T   A   M   P  nl   T   A   R   G   E   T
   S  nl   M   U   L   T   I   P   L   E  nl   S   A   V   E   _
   T   A   R   G   E   T   S  nl   t   e   x   t   /   h   t   m
   l  nl   t   e   x   t   /   _   m   o   z   _   h   t   m   l
   c   o   n   t   e   x   t  nl   t   e   x   t   /   _   m   o
   z   _   h   t   m   l   i   n   f   o  nl   U   T   F   8   _
   S   T   R   I   N   G  nl   C   O   M   P   O   U   N   D   _
   T   E   X   T  nl   T   E   X   T  nl   S   T   R   I   N   G
  nl   t   e   x   t   /   p   l   a   i   n   ;   c   h   a   r
   s   e   t   =   u   t   f   -   8  nl   t   e   x   t   /   p
   l   a   i   n  nl   t   e   x   t   /   x   -   m   o   z   -
   u   r   l   -   p   r   i   v  nl'''
MULTIPLE          : ''Error:\ target\ MULTIPLE\ not\ available
SAVE_TARGETS      : ''''
text/html         : '   <   m   e   t   a  sp   h   t   t   p   -   e   q   u   i   v
   =   "   c   o   n   t   e   n   t   -   t   y   p   e   "  sp
   c   o   n   t   e   n   t   =   "   t   e   x   t   /   h   t
   m   l   ;  sp   c   h   a   r   s   e   t   =   u   t   f   -
   8   "   >   <   p   r   e  sp   c   l   a   s   s   =   "   l
   a   n   g   -   b   a   s   h  sp   s   -   c   o   d   e   -
   b   l   o   c   k   "   >   <   c   o   d   e  sp   d   a   t
   a   -   h   i   g   h   l   i   g   h   t   e   d   =   "   y
   e   s   "  sp   c   l   a   s   s   =   "   h   l   j   s  sp
   l   a   n   g   u   a   g   e   -   b   a   s   h   "   >   x
   c   l   i   p  sp   -   s   e   l  sp   c   l   i   p  sp   -
   o  sp   -   t  sp   T   I   M   E   S   T   A   M   P   <   /
   c   o   d   e   >   <   /   p   r   e   >'''
text/_moz_htmlcontext: '   < nul   h nul   t nul   m nul   l nul  sp nul   i nul   t nul
   e nul   m nul   s nul   c nul   o nul   p nul   e nul   = nul
   " nul   " nul  sp nul   i nul   t nul   e nul   m nul   t nul
   y nul   p nul   e nul   = nul   " nul   h nul   t nul   t nul
   p nul   s nul   : nul   / nul   / nul   s nul   c nul   h nul
   e nul   m nul   a nul   . nul   o nul   r nul   g nul   / nul
   Q nul   A nul   P nul   a nul   g nul   e nul   " nul  sp nul
   c nul   l nul   a nul   s nul   s nul   = nul   " nul   h nul
   t nul   m nul   l nul   _ nul   _ nul   r nul   e nul   s nul
   p nul   o nul   n nul   s nul   i nul   v nul   e nul  sp nul
   " nul  sp nul   l nul   a nul   n nul   g nul   = nul   " nul
   e nul   n nul   " nul   > nul   < nul   b nul   o nul   d nul
   y nul  sp nul   c nul   l nul   a nul   s nul   s nul   = nul
   " nul   q nul   u nul   e nul   s nul   t nul   i nul   o nul
   n nul   - nul   p nul   a nul   g nul   e nul  sp nul   u nul
   n nul   i nul   f nul   i nul   e nul   d nul   - nul   t nul
   h nul   e nul   m nul   e nul  sp nul   t nul   h nul   e nul
   m nul   e nul   - nul   d nul   a nul   r nul   k nul   " nul
   > nul   < nul   d nul   i nul   v nul  sp nul   c nul   l nul
   a nul   s nul   s nul   = nul   " nul   c nul   o nul   n nul
    ....
   i nul   v nul   > nul   < nul   / nul   d nul   i nul   v nul
   > nul   < nul   / nul   d nul   i nul   v nul   > nul   < nul
   / nul   d nul   i nul   v nul   > nul   < nul   / nul   d nul
   i nul   v nul   > nul   < nul   / nul   d nul   i nul   v nul
   > nul   < nul   / nul   d nul   i nul   v nul   > nul   < nul
   / nul   d nul   i nul   v nul   > nul   < nul   / nul   b nul
   o nul   d nul   y nul   > nul   < nul   / nul   h nul   t nul
   m nul   l nul   > nul'''
text/_moz_htmlinfo: '   0 nul   , nul   0 nul'''
UTF8_STRING       : '   x   c   l   i   p  sp   -   s   e   l  sp   c   l   i   p  sp
   -   o  sp   -   t  sp   T   I   M   E   S   T   A   M   P'''
COMPOUND_TEXT     : '   x   c   l   i   p  sp   -   s   e   l  sp   c   l   i   p  sp
   -   o  sp   -   t  sp   T   I   M   E   S   T   A   M   P'''
TEXT              : '   x   c   l   i   p  sp   -   s   e   l  sp   c   l   i   p  sp
   -   o  sp   -   t  sp   T   I   M   E   S   T   A   M   P'''
STRING            : '   x   c   l   i   p  sp   -   s   e   l  sp   c   l   i   p  sp
   -   o  sp   -   t  sp   T   I   M   E   S   T   A   M   P'''
text/plain;charset=utf-8: '   x   c   l   i   p  sp   -   s   e   l  sp   c   l   i   p  sp
   -   o  sp   -   t  sp   T   I   M   E   S   T   A   M   P'''
text/plain        : '   x   c   l   i   p  sp   -   s   e   l  sp   c   l   i   p  sp
   -   o  sp   -   t  sp   T   I   M   E   S   T   A   M   P'''
text/x-moz-url-priv: '   h nul   t nul   t nul   p nul   s nul   : nul   / nul   / nul
   s nul   t nul   a nul   c nul   k nul   o nul   v nul   e nul
   r nul   f nul   l nul   o nul   w nul   . nul   c nul   o nul
   m nul   / nul   q nul   u nul   e nul   s nul   t nul   i nul
   o nul   n nul   s nul   / nul   7 nul   9 nul   0 nul   5 nul
   8 nul   4 nul   1 nul   1 nul   / nul   x nul   c nul   l nul
   i nul   p nul   - nul   t nul   i nul   m nul   e nul   s nul
   t nul   a nul   m nul   p nul   - nul   t nul   i nul   m nul
   e nul   - nul   u nul   n nul   i nul   t nul   s nul'''

Null bytes!

Well, then we can see: TARGETS text/_moz_htmlcontext and text/x-moz-url-priv output's are encoded in UTF-16!

For this you could use tr -d \\0 but you'd better use a conversion tool:

clip="$(xclip -sel c -o -t text/x-moz-url-priv | iconv -f utf16)"
echo "$clip"

or

clip="$(xclip -sel c -o -t text/x-moz-url-priv | recode -f u7..u8)"
echo "$clip"
https://stackoverflow.com/questions/749544/pipe-to-from-the-clipboard-in-a-bash-script?page=2&tab=scoredesc#tab-top

Final version

For final version, I've replaced %q by %s in order to obtain a cleaner output, and added one switch: -b for binary mode, where output are reformated by od -ta -An, then newlines and exessive spaces are dropped.

clipDump() {
    local _Targets _target _store _errMsg
    local -i _errFD _binMode=0
    [[ $1 == -b ]]  && shift && _binMode=1
    mapfile -t _Targets < <(xclip -selection ${1:-primary} -o -t TARGETS)
    for _target in "${_Targets[@]}"; do
        exec {_errFD}<> <(:)
        if ((_binMode)); then
            _store="$(
                xclip -selection ${1:-primary} -t $_target -o 2>&$_errFD |
                    od -ta -An |
                    tr -d \\n |
                    sed '
                        s/^[[:space:]]*//;
                        s/[[:space:]]*$//;
                        s/[[:space:]]\+/ /g;
                ')"
        else
            _store="$(xclip -selection ${1:-primary} -t $_target -o 2>&$_errFD)"
        fi
        IFS= read -ru $_errFD -t .01 _errMsg
        exec {_errFD}>&-
        printf "%-30s: %s\e[31m%s\e[0m\n" \
               $'\e[44;30m'"$_target"$'\e[0m' "$_store" "$_errMsg"
    done
}
clipDump
TIMESTAMP         : 2020839389
TARGETS           : TIMESTAMP
TARGETS
MULTIPLE
text/html
text/_moz_htmlcontext
text/_moz_htmlinfo
UTF8_STRING
COMPOUND_TEXT
TEXT
STRING
text/plain;charset=utf-8
text/plain
text/x-moz-url-priv
MULTIPLE          : Error: target MULTIPLE not available
text/html         : <meta http-equiv="content-type" content="text/html; charset=utf-8"><pre class="lang-bash s-code-block"><code data-highlighted="yes" class="hljs language-bash">clipDump</code></pre>
bash: warning: command substitution: ignored null byte in input
text/_moz_htmlcontext: <html itemscope="" itemtype="https://schema.org/QAPage" class="html__responsive " lang="en"><body class="question-page unified-theme theme-dark"><div class="container"><div id="content" class="snippet-hidden"><div itemprop="mainEntity" itemscope="" itemtype="https://schema.org/Question"><div class="inner-content clearfix"><div id="mainbar" role="main" aria-label="question and answers"><div id="answers"><div id="answer-79059847" class="answer js-answer highlighted-post" data-answerid="79059847" data-parentid="749544" data-score="2" data-position-on-page="27" data-highest-scored="0" data-question-has-accepted-highest-score="0" itemprop="suggestedAnswer" itemscope="" itemtype="https://schema.org/Answer"><div class="post-layout"><div class="answercell post-layout--right"><div class="inline-editor" style=""><form class="inline-post" action="/posts/79059847/edit-submit/29257632-6d0e-4ec5-a1f3-a71b7f11b79d" method="post" data-post-params="{&quot;is_suggested_edit&quot;:false,&quot;post_type&quot;:2,&quot;owner&quot;:1,&quot;PostId&quot;:79059847}"><div id="post-editor-79059847" class="post-editor js-post-editor d-flex fd-column g4"><div id="wmd-preview-79059847" class="s-prose mb16 wmd-preview js-wmd-preview"><pre class="lang-bash s-code-block"></pre></div></div></form></div></div></div></div></div></div></div></div></div></div></body></html>
bash: warning: command substitution: ignored null byte in input
text/_moz_htmlinfo: 0,0
UTF8_STRING       : clipDump
COMPOUND_TEXT     : clipDump
TEXT              : clipDump
STRING            : clipDump
text/plain;charset=utf-8: clipDump
text/plain        : clipDump
bash: warning: command substitution: ignored null byte in input
text/x-moz-url-priv: https://stackoverflow.com/questions/749544/pipe-to-from-the-clipboard-in-a-bash-script/79059847#79059847
clipDump -b
TIMESTAMP         : 2 0 2 0 8 9 8 7 4 8 nl
TARGETS           : T I M E S T A M P nl T A R G E T S nl M U L T I P L E nl t e x t / h t m l nl t e x t / _ m o z _ h t m l c o n t e x t nl t e x t / _ m o z _ h t m l i n f o nl U T F 8 _ S T R I N G nl C O M P O U N D _ T E X T nl T E X T nl S T R I N G nl t e x t / p l a i n ; c h a r s e t = u t f - 8 nl t e x t / p l a i n nl t e x t / x - m o z - u r l - p r i v nl
MULTIPLE          : Error: target MULTIPLE not available
text/html         : < m e t a sp h t t p - e q u i v = " c o n t e n t - t y p e " sp c o n t e n t = " t e x t / h t m l ; sp c h a r s e t = u t f - 8 " > < p r e sp c l a s s = " l a n g - b a s h sp s - c o d e - b l o c k " > < c o d e sp d a t a - h i g h l i g h t e d = " y e s " sp c l a s s = " h l j s sp l a n g u a g e - b a s h " > c l i p D u m p sp - b < / c o d e > < / p r e >
text/_moz_htmlcontext: < nul h nul t nul m nul l nul sp nul i nul t nul e nul m nul s nul c nul o nul p nul e nul = nul " nul " nul sp nul i nul t nul e nul m nul t nul y nul p nul e nul = nul " nul h nul t nul t nul p nul s nul : nul / nul / nul s nul c nul h nul e nul m nul a nul . nul o nul r nul g nul / nul Q nul A nul P ... = nul " nul l nul a nul n nul g nul - nul b nul a nul s nul h nul sp nul s nul - nul c nul o nul d nul e nul - nul b nul l nul o nul c nul k nul " nul > nul < nul / nul p nul r nul e nul > nul < nul / nul d nul i nul v nul > nul < nul / nul d nul i nul v nul > nul < nul / nul f nul o nul r nul m nul > nul < nul / nul d nul i nul v nul > nul < nul / nul d nul i nul v nul > nul < nul / nul d nul i nul v nul > nul < nul / nul d nul i nul v nul > nul < nul / nul d nul i nul v nul > nul < nul / nul d nul i nul v nul > nul < nul / nul d nul i nul v nul > nul < nul / nul d nul i nul v nul > nul < nul / nul d nul i nul v nul > nul < nul / nul d nul i nul v nul > nul < nul / nul b nul o nul d nul y nul > nul < nul / nul h nul t nul m nul l nul > nul
text/_moz_htmlinfo: 0 nul , nul 0 nul
UTF8_STRING       : c l i p D u m p sp - b
COMPOUND_TEXT     : c l i p D u m p sp - b
TEXT              : c l i p D u m p sp - b
STRING            : c l i p D u m p sp - b
text/plain;charset=utf-8: c l i p D u m p sp - b
text/plain        : c l i p D u m p sp - b
text/x-moz-url-priv: h nul t nul t nul p nul s nul : nul / nul / nul s nul t nul a nul c nul k nul o nul v nul e nul r nul f nul l nul o nul w nul . nul c nul o nul m nul / nul q nul u nul e nul s nul t nul i nul o nul n nul s nul / nul 7 nul 4 nul 9 nul 5 nul 4 nul 4 nul / nul p nul i nul p nul e nul - nul t nul o nul - nul f nul r nul o nul m nul - nul t nul h nul e nul - nul c nul l nul i nul p nul b nul o nul a nul r nul d nul - nul i nul n nul - nul a nul - nul b nul a nul s nul h nul - nul s nul c nul r nul i nul p nul t nul / nul 7 nul 9 nul 0 nul 5 nul 9 nul 8 nul 4 nul 7 nul # nul 7 nul 9 nul 0 nul 5 nul 9 nul 8 nul 4 nul 7 nul

Sending datas to clipboard

For posting on this site, for sample, I often use something like:

COLUMNS=88 man -Len -Pcat xclip |
    sed '/^[[:space:]]*\(-[iot]\|-sel\)/,/^ *$/s/^/> /p;d' |
    xclip

Then I could simply paste:

   -i, -in
          read text into X selection from standard input or files (default)

   -o, -out
          print  the selection to standard out (generally for piping to a file or
          program)

   -t, -target
          specify  a particular data format using the given target atom.  With -o
          the special target atom name "TARGETS" can be used to  get  a  list  of
          valid target atoms for this selection.  For more information about tar‐
          get atoms refer to ICCCM section 2.6.2

   -selection
          specify  which X selection to use, options are "primary" to use XA_PRI‐
          MARY  (default),  "secondary"  for  XA_SECONDARY  or  "clipboard"   for
          XA_CLIPBOARD

( There is no need to precise: xclip -i -sel p. ;-)

Upvotes: 2

tleb
tleb

Reputation: 4606

Under Wayland

# Install using your package manager:
apt-get install wl-clipboard
pacman -S wl-clipboard
dnf install wl-clipboard

# Now, you can use:
$ echo foo | wl-copy
$ wl-paste
foo

If you do not have access to apt-get nor pacman, nor dnf, sources are hosted on GitHub.

Under the X Window System

# Install using your package manager:
apt-get install xclip
pacman -S xclip
dnf install xclip

# Then, add aliases for Bash:
echo 'alias setclip="xclip -selection c"' >> ~/.bash_aliases
echo 'alias getclip="xclip -selection c -o"' >> ~/.bash_aliases

# Or, for fish shell:
echo 'abbr setclip "xclip -selection c"' >> ~/.config/fish/config.fish
echo 'abbr getclip "xclip -selection c -o"' >> ~/.config/fish/config.fish

# Now, you can use (don't forget to reload your configs!):
$ echo foo | setclip
$ getclip
foo

If you do not have access to apt-get nor pacman, nor dnf, the sources are available on SourceForge.

Upvotes: 251

mrkbutty
mrkbutty

Reputation: 599

If you are using "Windows Terminal" to ssh into a Linux host, you can use the following little script to copy a file to the clipboard of the windows host:

# Clipfile
#  - Sends a file into the Windows Terminal clipboard
printf $'\e]52;c;%s\a' "$(base64 ${1:?})"

I'm not sure if this works with other terminal and console programs???

Thanks to @MrCalvin answer at: https://superuser.com/questions/1705770/copy-data-from-linux-console-to-windowshost-clipboard-using-windows-terminal?newreg=8ad2f39ec3f54a659b0c9e295540bbf1

Upvotes: 1

jtruelove
jtruelove

Reputation: 3396

On macOS, use the built-in pbcopy and pbpaste commands.

For example, if you run

cat ~/.bashrc | pbcopy

the contents of the ~/.bashrc file will be available for pasting with the Cmd + V shortcut.

To save the current clipboard to a file, redirect the output pbpaste to a file:

pbpaste > my_clipboard.txt

Upvotes: 194

Mahdi-Malv
Mahdi-Malv

Reputation: 19250

For mac you can use this function which uses pbcopy and pbpaste, but a little easier:

Add this to your .bashrc or .zshrc:

clp() {
  if [[ -z "$1" ]]
  then
    # No input - act as paste
    pbpaste;
  else
    # Input exists - act as copy
    echo "$1" | pbcopy;
  fi
}

To copy use clp "Content" and to paste use clp

Upvotes: 2

Ilyich
Ilyich

Reputation: 5796

A way to paste from the clipboard to a file without any tools except echo.

  1. Escape single quotes in the text you want to paste: replace all occurrences of ' with '\'' and copy the result to clipboard.
  2. Type echo -n '
  3. Press Shift + Insert
  4. Type ' > filename.txt
  5. Press Enter

Basically you're doing this:

echo -n 'copied "text" with '\''single quotes'\'' escaped' > filename.txt

It works even if the copied text has new lines.

Upvotes: 0

Andrew_1510
Andrew_1510

Reputation: 13556

xsel on Debian/Ubuntu/Mint

# append to clipboard:
cat 'the file with content' | xsel -ab

# or type in the happy face :) and ...
echo 'the happy face :) and content' | xsel -ib

# show clipboard
xsel -ob

# Get more info:
man xsel

Install

sudo apt-get install xsel

Upvotes: 57

Harry Moreno
Harry Moreno

Reputation: 11643

The Ruby oneliner inspired me to try with Python.

Say we want a command that indents whatever is in the clipboard with four spaces. It is perfect for sharing snippets on Stack Overflow.

$ pbpaste | python -c "import sys
 for line in sys.stdin:
   print(f'    {line}')" | pbcopy

That's not a typo. Python needs newlines to do a for loop. We want to alter the lines in one pass to avoid building up an extra array in memory.

If you don't mind building the extra array try:

$ pbpaste | python -c "import sys; print(''.join([f'    {l}' for l in sys.stdin]))" | pbcopy

but honestly awk is better for this than python. I defined this alias in my ~/.bashrc file

alias indent="pbpaste | awk '{print \"    \"\$0}' | pbcopy"

Now when I run indent, whatever is in my clipboard is indented.

Upvotes: 2

whati001
whati001

Reputation: 389

I just searched the same stuff in my KDE environment.

Feel free to use clipcopy and clippaste.

KDE:

> echo "TEST CLIP FROM TERMINAL" | clipcopy
> clippaste
TEST CLIP FROM TERMINAL

Upvotes: 8

alshaboti
alshaboti

Reputation: 683

This function will test what clipboard exists and use it.

To verify copy paste into your shell, and then call the function clippaste:

clippaste () {
    if [[ $OSTYPE == darwin* ]]
    then
            pbpaste
    elif [[ $OSTYPE == cygwin* ]]
    then
            cat /dev/clipboard
    else
            if command -v xclip &> /dev/null
            then
                    xclip -out -selection clipboard
            elif command -v xsel
            then
                    xsel --clipboard --output
            else
                    print "clipcopy: Platform $OSTYPE not supported or xclip/xsel not installed" >&2
                    return 1
            fi
    fi
}

Upvotes: 0

Jens Timmerman
Jens Timmerman

Reputation: 9816

On Wayland, xcopy doesn't seem to work. Use wl-clipboard instead.

E.g., on Fedora:

sudo dnf install wl-clipboard

tree | wl-copy

wl-paste > file

Upvotes: 8

Skulas
Skulas

Reputation: 507

pbcopy is built into OS X:

Copying the content of file .bash_profile:

cat ~/.bash_profile | pbcopy

Upvotes: 5

SergioAraujo
SergioAraujo

Reputation: 11820

I have found a good reference: How to target multiple selections with xclip

In my case, I would like to paste content on the clipboard and also to see what is been pasted there, so I used also the tee command with a file descriptor:

echo "just a test" | tee >(xclip -i -selection clipboard)

>() is a form of process substitution. Bash replaces each with the path to a file descriptor which is connected to the standard input of the program within the parentheses.

The teecommand forks your command allowing you to "pipe its content" and see the result on standard output "stdout".

You can also create aliases to get and write on the clipboard, allowing you to use "pbcopy" and "pbpaste" as if you where on Mac. In my case, as I use Z shell (zsh), I have this in my aliases file:

(( $+commands[xclip] )) && {
    alias pbpaste='xclip -i -selection clipboard -o'
    alias pbcopy='xclip -selection clipboard'
}

The (( $+command[name] )) in Z shell tests if the command "name" is installed on your system, and then both aliases are grouped with {}. The && is a binary AND; if a then b, hence if you have xclip then the aliases will be set.

echo "another test" | tee >(pbcopy)

To get your clipboard content, just type:

pbpaste | "any-command-you-need-here"

Upvotes: 7

knowledge_is_power
knowledge_is_power

Reputation: 898

On the Windows Subsystem for Linux (WSL) you can copy to the clipboard with clip.exe:

cat file | clip.exe

Keep in mind to use the | pipe command. And not a > command, since that will not work.

Upvotes: 41

Braden Best
Braden Best

Reputation: 8998

There are a couple of ways. Some of the ways that have been mentioned include (I think) tmux, Screen, Vim, Emacs, and the shell. I don't know Emacs or Screen, so I'll go over the other three.

Tmux

While not an X selection, tmux has a copy mode accessible via prefix-[ (prefix is Ctrl + B by default). The buffer used for this mode is separate and exclusive to tmux, which opens up quite a few possibilities and makes it more versatile than the X selections in the right situations.

To exit this mode, hit Q; to navigate, use your Vim or Emacs binding (default = Vim), so hjkl for movement, v/V/C-v for character/line/block selection, etc. When you have your selection, hit Enter to copy and exit the mode.

To paste from this buffer, use prefix-].

Shell

Any installation of X11 seems to come with two programs by default: xclip and xsel (kind of like how it also comes with both startx and xinit). Most of the other answers mention xclip, and I really like xsel for its brevity, so I'm going to cover xsel.

From xsel(1x):

Input options \

-a, --append \

append standard input to the selection. Implies -i.

-f, --follow \

append to selection as standard input grows. Implies -i.

-i, --input \

read standard input into the selection.

Output options \

-o, --output \

write the selection to standard output.

Action options \

-c, --clear \

clear the selection. Overrides all input options.

-d, --delete \

Request that the current selection be deleted. This not only clears the selection, but also requests to the program in which the selection resides that the selected contents be deleted. Overrides all input options.

Selection options \

-p, --primary \

operate on the PRIMARY selection (default).

-s, --secondary \

operate on the SECONDARY selection.

-b, --clipboard \

operate on the CLIPBOARD selection.

And that's about all you need to know. p (or nothing) for PRIMARY, s for SECONDARY, b for CLIPBOARD, o for output.

Example: say I want to copy the output of foo from a TTY and paste it to a webpage for a bug report. To do this, it would be ideal to copy to/from the TTY/X session. So the question becomes how do I access the clipboard from the TTY?

For this example, we'll assume the X session is on display :1.

$ foo -v
Error: not a real TTY
details:
blah blah @ 0x0000000040abeaf4
blah blah @ 0x0000000040abeaf8
blah blah @ 0x0000000040abeafc
blah blah @ 0x0000000040abeb00
...
$ foo -v | DISPLAY=:1 xsel -b # copies it into clipboard of display :1

Then I can Ctrl + V it into the form as per usual.

Now say that someone on the support site gives me a command to run to fix the problem. It's complicated and long.

$ DISPLAY=:1 xsel -bo
sudo foo --update --clear-cache --source-list="http://foo-software.com/repository/foo/debian/ubuntu/xenial/164914519191464/sources.txt"
$ $(DISPLAY=:1 xsel -bo)
Password for braden:
UPDATING %%%%%%%%%%%%%%%%%%%%%%% 100.00%
Clearing cache...
Fetching sources...
Reticulating splines...
Watering trees...
Climbing mountains...
Looking advanced...
Done.
$ foo
Thank you for your order. A pizza should arrive at your house in the next 20 minutes. Your total is $6.99

Pizza ordering seems like a productive use of the command line.

...moving on.

Vim

If compiled with +clipboard (This is important! Check your vim --version), Vim should have access to the X PRIMARY and CLIPBOARD selections. The two selections are accessible from the * and + registers, respectively, and may be written to and read from at your leisure the same as any other register.

For example:

:%y+    ; copy/yank (y) everything (%) into the CLIPBOARD selection (+)
"+p     ; select (") the CLIPBOARD selection (+) and paste/put it
ggVG"+y ; Alternative version of the first example

If your copy of Vim doesn't directly support access to X selections, though, it's not the end of the world. You can just use the xsel technique as described in the last section.

:r ! xsel -bo ; read  (r) from the stdout of (!) `xsel -bo`
:w ! xsel -b  ; write (w) to the stdin of    (!) `xsel -b`

Bind a couple key combos and you should be good.

Upvotes: 4

thebunnyrules
thebunnyrules

Reputation: 1670

Install the xcopy utility and when you're in the Terminal, input:

Copy

Thing_you_want_to_copy | xclip -selection c

Paste

myvariable=$(xclip -selection clipboard -o)

I noticed a lot of answers recommended pbpaste and pbcopy. If you're into those utilities, but for some reason they are not available in your repository, you can always make an alias for the xcopy commands and call them pbpaste and pbcopy.

alias pbcopy="xclip -selection c"
alias pbpaste="xclip -selection clipboard -o"

So then it would look like this:

Thing_you_want_to_copy | pbcopy
myvariable=$(pbpaste)

An answer located in one of the comments written by a user called doug work for me. Since I found it so helpful, I decided to restate in an answer.

Upvotes: 22

VonC
VonC

Reputation: 1327164

From this thread, there is an option which does not require installing any gclip/xclip/xsel third-party software.

A Perl script (since Perl is usually always installed)

use Win32::Clipboard;
print Win32::Clipboard::GetText();

Upvotes: 2

lurix66
lurix66

Reputation: 552

Yesterday I found myself with the question: "How can I share the clipboard between different user sessions?". When switching between sessions with Ctrl + Alt + F7 - Ctrl + Alt + F8, in fact, you can't paste what you copied.

I came up with the following quick & dirty solution, based on a named pipe. It is surely quite bare and raw, but I found it functional:

user1@host:~$ mkfifo /tmp/sharedClip

then in the sending terminal

user1@host:~$ cat > /tmp/sharedClip

last, in the receiving terminal:

user2@host:~$ cat /tmp/sharedClip

Now, you type or paste anything in the first terminal, and (after hitting Return), it will appear immediately in the receiving terminal, from where you can copy and paste again anywhere you like.

Of course this doesn't just strictly take the content from user1's clipboard to make it available in user2's clipboard, but rather it requires an additional pair of Paste & Copy clicks.

Upvotes: 4

Wolfgang Fahl
Wolfgang Fahl

Reputation: 15576

Here is a ready-to-use Bash script for reading the clipboard which works on multiple platforms.

Please edit the script here if you add functionality (e.g., more platforms).

#!/bin/bash
# WF 2013-10-04
#
# Multi-platform clipboard read access
#
# Supports
#   Mac OS X
#   Git shell / Cygwin (Windows)
#   Linux (e.g., Ubuntu)

#
# Display an error
#
error() {
  echo "error: $1" 1>&2
  exit 1
}

#
# getClipboard
#
function getClipboard() {
 os=`uname`
      case $os in
        # Git Bash  (Windows)
        MINGW32_NT-6.1)
          cat /dev/clipboard;;
        # Mac OS X
        Darwin*)
          pbpaste;;
        # Linux
        Linux*)
          # Works only for the X clipboard - a check that X is running might be due
          xclip -o;;
        *)
          error "unsupported os $os";;
      esac
}

tmp=/tmp/clipboard$$
getClipboard >$tmp
cat $tmp
# Comment out for debugging
rm $tmp

Upvotes: 17

lhunath
lhunath

Reputation: 125476

There are a wealth of clipboards you could be dealing with. I expect you're probably a Linux user who wants to put stuff in the X Windows primary clipboard. Usually, the clipboard you want to talk to has a utility that lets you talk to it.

In the case of X, there's xclip (and others). xclip -selection c will send data to the clipboard that works with Ctrl + C, Ctrl + V in most applications.

If you're on Mac OS X, there's pbcopy. E.g., cat example.txt | pbcopy

If you're in Linux terminal mode (no X) then look into gpm or Screen which has a clipboard. Try the Screen command readreg.

Under Windows 10+ or Cygwin, use /dev/clipboard or clip.

Upvotes: 1138

Norman H
Norman H

Reputation: 2262

On Windows (with Cygwin) try cat /dev/clipboard or echo "foo" > /dev/clipboard as mentioned in this article.

Upvotes: 11

doug
doug

Reputation: 4060

Make sure you are using alias xclip="xclip -selection c" or else you won't be able to paste using Ctrl+v.

Example: After running echo -n test | xclip, Ctrl+v will paste test

Upvotes: 366

Evan Conrad
Evan Conrad

Reputation: 4389

2018 answer

Use clipboard-cli. It works with macOS, Windows, Linux, OpenBSD, FreeBSD, and Android without any real issues.

Install it with:

npm install -g clipboard-cli

Then you can do:

echo foo | clipboard 

If you want, you can alias to cb by putting the following in your .bashrc, .bash_profile, or .zshrc:

alias cb=clipboard

Upvotes: 70

otto
otto

Reputation: 2033

In Linux this works:

cat filename | xclip

Upvotes: 5

horta
horta

Reputation: 1130

If you're like me and run on a Linux server without root privileges and there isn't any xclip or GPM you could workaround this issue by just using a temporary file. For example:

$ echo "Hello, World!" > ~/clip
$ echo `cat ~/clip`
Hello, World!

Upvotes: 0

Stenemo
Stenemo

Reputation: 619

Copy and paste to clipboard in Windows (Cygwin):

See:

$ clip.exe -?

CLIP
Description:
    Redirects output of command line tools to the Windows clipboard.
    This text output can then be pasted into other programs.
Parameter List:
/?                  Displays this help message.
Examples:
DIR | CLIP          Places a copy of the current directory
                        listing into the Windows clipboard.
CLIP < README.TXT   Places a copy of the text from readme.txt
                        on to the Windows clipboard.

Also getclip (it can be used instead of Shift + Ins!) and putclip (echo oaeuoa | putclip.exe to put it into clip) exist.

Upvotes: 5

jiahut
jiahut

Reputation: 1531

In macOS, use pbpaste.

For example:

Update the clipboard

pbpaste  | ruby -ne ' puts "\|" + $_.split( )[1..4].join("\|") ' | pbcopy

Upvotes: 1

Martin Fischer
Martin Fischer

Reputation: 59

  xsel -b

Does the job for X Window, and it is mostly already installed. A look in the man page of xsel is worth the effort.

Upvotes: 5

tysweat
tysweat

Reputation: 79

This is a simple Python script that does just what you need:

#!/usr/bin/python

import sys

# Clipboard storage
clipboard_file = '/tmp/clipboard.tmp'

if(sys.stdin.isatty()): # Should write clipboard contents out to stdout
    with open(clipboard_file, 'r') as c:
        sys.stdout.write(c.read())
elif(sys.stdout.isatty()): # Should save stdin to clipboard
    with open(clipboard_file, 'w') as c:
        c.write(sys.stdin.read())

Save this as an executable somewhere in your path (I saved it to /usr/local/bin/clip. You can pipe in stuff to be saved to your clipboard...

echo "Hello World" | clip

And you can pipe what's in your clipboard to some other program...

clip | cowsay
 _____________
< Hello World >
 -------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Running it by itself will simply output what's in the clipboard.

Upvotes: 6

jeng
jeng

Reputation: 21

A few Windows programs I wrote years ago. They allow you dump, push, append and print the clipboard. It works like this:

dumpclip | perl -pe "s/monkey/chimp/g;" | pushclip

It includes source code: cmd_clip.zip

Upvotes: 2

Related Questions