How to only append to clipboard (but not overwrite current data)?

I have a rather large file, I need to copy the entire contents somewhere, but when I scroll down the page all the data I have selected becomes unselected. I could just copy and paste block by block, but I would find it much easier as there is a lot of data, to just be able to append the contents to the end of the current clipboard data. Is that possible?

That is so that I can have a keyboard shortcut which will enable me to copy this to the clipboard:

I am some nice new text.

When this is what is already there:

I am the old text.

And have it look like this when pasted:

I am the old text.
I am some nice new text.

So there are 3 things that I would really like from this (I would have 3 separate keyboard shortcuts to do this):

  1. Append the data to the end of the clipboard and have it put in a RETURN before it (as shown in the example above).

  2. Append the data to the end of the clipboard but have it so that there is not RETURN before it so that it would continue on on the same line initially.

  3. Have all this but so that the data is put at the beginning of the clipboard before all the data which is currently there.

I am running Ubuntu GNOME 16.04 with GNOME 3.20.


It is simple, but you need to install the tool xsel first:

sudo apt-get install xsel

TL;DR: Here are the commands you probably want to use for your shortcuts in the end. I am using the versions with printf everywhere for uniformity and easier customization, even if a simpler variant would have been enough:

  • Append selection to end of clipboard directly:

    bash -c 'printf "%b%b" "$(xsel -b)" "$(xsel)" | xsel -ib ; xsel -c'
    
  • Append selection to end of clipboard after a line break:

    bash -c 'printf "%b\n%b" "$(xsel -b)" "$(xsel)" | xsel -ib ; xsel -c'
    
  • Append selection to beginning of clipboard directly:

    bash -c 'printf "%b%b" "$(xsel)" "$(xsel -b)" | xsel -ib ; xsel -c'
    
  • Append selection to beginning of clipboard after a line break:

    bash -c 'printf "%b\n%b" "$(xsel)" "$(xsel -b)" | xsel -ib ; xsel -c'
    

They are all including the primary buffer reset after appending to the clipboard to prevent double appending the same content. If you do not want that, remove the ; xsel -c from the end of each command.


Long explanation:

You have to know that X contains 3 buffers, the primary selection, the secondary selection and the clipboard.

You know the clipboard from Ctrl+C, Ctrl+V etc. It's the buffer you normally use to copy and paste stuff.

The primary selection though is the buffer that always automatically contains the text you select, no matter which window it is in and without any additional user interaction.
We just have one problem: The buffer gets updated the moment you select a text snippet, but it does not get cleared when you click anywhere else to cancel the selection. It will still contain the content of your last selection.

The secondary selection is only used by few programs and not interesting for us here.


That means we can mimic the behaviour of Ctrl+C with this command below which copies the primary selection (last highlighted text) to the clipboard:

xsel | xsel -ib

xsel without any arguments prints the primary selection's content to STDOUT. xsel -ab writes (-i) the data from STDIN to the clipboard (-b).


To directly append data to the current clipboard content (without line break in between) instead of replacing it, we use the -a option instead of -i. This command will append the last selected text snippet to the current clipboard content:

xsel | xsel -ab

If you really want an additional line break or any other formatting, we can pipe the data through printf or any other tool that you want to use to process it. Here's an example that reads both the last selection and the current clipboard content and joins them together using a newline:

printf "%b\n%b" "$(xsel -b)" "$(xsel)" | xsel -ib

xsel -b returns the current clipboard content. The format string of printf uses %b as placeholder for the arguments, \n represents a line break. You can find out more about printf by typing man printf.

By switching the two arguments in the end of the string, you can reverse their order and append to the beginning instead of the end.


If you want to avoid appending the same data to the clipboard twice accidentally (you will have to select it again if you want to append it twice!), you can clear the primary selection buffer manually after the command has been performed using this:

xsel -c

Simply run that after the basic clipboard appending command, like that:

printf "%b\n%b" "$(xsel -b)" "$(xsel)" | xsel -ib ; xsel -c

So knowing all this, you can write commands for your keyboard shortcuts that do exactly what you want, but remember that our one-liners all make heavy use of Bash features like piping, so you need to run them with Bash:

bash -c 'COMMAND'

See the TL;DR section at the top of the answer for a command list suitable for creating shortcuts.


X server has multiple clipboards. The one with Ctrl + C is referred to as clipboard, the one where you highlight something is called primary. xclip allows pasting output of either . For example I copied portion of your question, but highlighted some other text in terminal:

enter image description here

You can further use that idea in a script that is connected to keyboard shortcut. In fact, I have written a script , which is posted as github gist

Basic idea is to bind it to keyboard shortcut. Highlight what you want appended, then press the shortcut. For instance, I've bound mine to Ctrl+Alt+V . Exact command is python /path/to/file.py

Example of Usage:

  1. Highlight the I have a rather large file part from your post and copy with Ctrl + C
  2. Highlight something else , for example That is so that I can have a keyboard shortcut
  3. Press your shortcut ( mine was Ctrl+Alt+V)
  4. Release the appended clipboard somewhere with Ctrl + V . The resulting output is: I have a rather large fileThat is so that I can have a keyboard shortcut

Script source

 import gi
    gi.require_version('Notify', '0.7')
    from gi.repository import Notify
    import subprocess
    import os
    import sys

    # This script is meant to be bound to keyboard shortcut

    def send_notification(title, text):
        Notify.init(sys.argv[0])
        n = Notify.Notification.new(title, text)
        n.show()


    def run_cmd(cmdlist):
        # function for running 
        try:
            stdout = subprocess.check_output(cmdlist)
        except subprocess.CalledProcessError:
              send_notification(sys.argv[0],"Clipboard error")
              sys.exit(1)
        else:
            if stdout:
                return  stdout



    # get contents of both clipboards
    clip = run_cmd("xclip -o -sel clip".split())
    primary = run_cmd("xclip -o -sel primary".split())

    # write to temp file contents
    # of both clipboards appended
    temp_file = "/tmp/append.clip"
    f = open(temp_file, "w")
    f.write( clip + primary  )
    f.close()

    # Read the new contents into clipboard
    run_cmd(("xclip -sel clip " + temp_file).split())

    # clean up
    os.remove(temp_file)

Notes:

  • xclip must be installed via sudo apt-get install xclip
  • I've written a clipboard manager indicator for Ubuntu with Unity desktop, that can use regular expressions (sed and python's re style) to append a repeated string to the clipboard. For instance, if you frequently need to append same string over and over, you can use the following python re regex:

enter image description here


Here is another very easy method that uses a short Bash script. First make sure you have xclip installed. Then create your bash script as follows:

#!bin/bash
p=$(xclip -selection primary -o)
c=$(xclip -selection clipboard -o)
new=$'\n'
echo "$c$new$p" | xclip -selection clip

Let's name this file apndpc.sh and put it in some folder, say ~/myscripts Now bind a user defined key to this. Do this by System settings>> Keyboard and click on Shortcuts tab. Click on Custom Shortcuts and then click on + sign to add your desired key combination. In the command box put:

bash -c 'bash ~/myscripts/apndclp.sh '

Then define your key combination. I use ALT+3 to trigger the action.

That is it. You are ready for your large scale copying operation. Use the normal Ctrl+c (or righ click and select copy) to copy the first chunk of text. Select the next chunk (only select NOT copy) and then press your shortcut key (ATL+3). This will append the selected text to the clipboard. Keep doing that until you are done. Then paste as usual, ie. CTRL+v (or righclick and select paste) to dump the final accumulated text.

If you do not like string manipulation in the above script then use this script instead:

#!bin/bash
# this is another version of clipboard append tool
# here we use a temporary file to append highlighted text to the clipboard
# the temporary file is deleted at the end of the operation

tmpfile="file111000111"
xclip -selection clipboard -o  > $tmpfile   # first dump the current clipboard to the tmpfile
printf '\n' >> $tmpfile                     # then add new line
xclip -selection primary -o >> $tmpfile     # and finally add the highlighted text
cat $tmpfile | xclip -selection clip        # now read the file back into the clipboard
rm $tmpfile             # and remove the tempfile