有时,我的剪贴板中有一个文件或字符串列表,并且希望将其作为参数列表粘贴到 bash shell 中:
示例文件列表(仅作为示例):
createsnapshot.sh
directorylisting.sh
fetchfile.sh
我想要的是:
md5sum createsnapshot.sh directorylisting.sh fetchfile.sh
目前,我输入以下 hacky 命令行(文件名是从剪贴板粘贴的;列表可以包含几十行):
md5sum $(echo $(echo "
createsnapshot.sh
directorylisting.sh
fetchfile.sh
"))
这有几个缺点:
- 这很复杂
- 看起来不太好
- 它不支持包含空格的行
我还有什么其他选择?md5sum "
不起作用,因为在这种情况下我只得到一个带有多行字符串的参数。与此处文档类似。
并不总是如此md5sum
。也可以是tar
或git add
或du -hsc
。我不只是要求一种方法来获取这些文件的 md5 校验和。这样的情况每天大约会发生2-5次。
答案1
如果您不引用变量或虚拟变量,例如反引号调用(例如$(xclip -selection c -o)
(输出 X 剪贴板的内容)),则 shell 将拆分
$IFS
默认为\t
\n
和 的内容,并且它将扩展内容中存在的全局变量。在这种情况下(确保您首先检查剪贴板的内容),这就是您想要的:
md5sum `xclip -selection c -o`
笔记:
在您需要的命令周围有一个简短命名的包装器非常方便xclip
。
我用
#!/bin/sh
#filename: cb
if [ -n "$DISPLAY" ]; then
[ -t 0 ] && exec /usr/bin/xclip -selection c -o 2>/dev/null
/usr/bin/xclip -selection c
else
[ -t 0 ] && exec cat "/dev/shm/$TTY_DASHED"
cat > /dev/shm/"$TTY_DASHED"
fi
这允许我输入内容cb
来访问剪贴板并something | cb
写入内容。
DISPLAY
(如果我在 X 之外(=如果未设置),我会使用以我的终端命名的内存中文件作为我的剪贴板。env 变量在我的as withTTY_DASHED
中设置 ).profile
export TTY_DASHED=$(tty |tr / - | tail -c+2)
答案2
如果命令不使用 use stdin
,请使用xargs
,它读取输入并将其转换为参数(请注意,我使用该echo
命令来展示如何xargs
构建该命令):
$ xargs echo md5sum
# paste text
createsnapshot.sh
directorylisting.sh
fetchfile.sh
# press Ctrl-D to signify end of input
md5sum createsnapshot.sh directorylisting.sh fetchfile.sh
使用xargs
with -d '\n'
,以便将每一行视为一个完整的参数,尽管有空格:
$ xargs -d'\n' md5sum
# paste
a file with spaces
afilewithoutspaces
foo " " bar
# Ctrl D
md5sum: a file with spaces: No such file or directory
md5sum: afilewithoutspaces: No such file or directory
md5sum: foo " " bar: No such file or directory
如您所见,md5sum
无论文件名中的其他空格如何,都会打印每个文件名的错误。
如果您愿意使用xclip
,那么您可以通过管道或其他方式将其提供给 xargs:
xargs -a <(xclip -o) -d '\n' md5sum
xclip -o | xargs -d '\n' md5sum
这应该可以可靠地处理带有空格的文件名。
答案3
您可以设置一个包含文件名的变量。然后在命令中使用该变量。
$ #VAR='<paste filenames>':
$ VAR='createsnapshot.sh
> directorylisting.sh
> fetchfile.sh'
$ touch $VAR
$ ls -l $VAR
-rw-r--r-- 1 testuser testuser 0 nov 26 12:47 createsnapshot.sh
-rw-r--r-- 1 testuser testuser 0 nov 26 12:47 directorylisting.sh
-rw-r--r-- 1 testuser testuser 0 nov 26 12:47 fetchfile.sh
$ md5sum $VAR
d41d8cd98f00b204e9800998ecf8427e createsnapshot.sh
d41d8cd98f00b204e9800998ecf8427e directorylisting.sh
d41d8cd98f00b204e9800998ecf8427e fetchfile.sh
$ tar cf archive.tar $VAR
$ tar tf archive.tar
createsnapshot.sh
directorylisting.sh
fetchfile.sh
注意:$VAR
由于行结尾,需要在不带引号的情况下调用。您可以考虑使用VAR=$(echo "$VAR"|tr '\n' ' ') to be able to use quoted
$VAR`
另一种方法(基于上述)是在您的~/.bashrc
包含中编写一个函数:
fVAR ()
{
VAR="$@";
VAR=$(echo "$VAR"|tr '\n' ' ')
}
使用剪贴板内容调用该函数fVAR
,值可在以下位置找到$VAR
:
$ fVAR '<paste filenames>'
$ md5sum "$VAR"
答案4
set --
while IFS= read -r in
do set -- "$@" "$in"
done
...然后按您的移位插入键,然后Ctrl+D一次(或两次),然后你的粘贴的每一行都可以被逐字地拥有(无 NUL)in$1
和$2
等等$3
,并且整个输入数组可以作为连接在$IFS
in的第一个字符上的单个字符串进行寻址"$*"
,或者作为 in 的单独字符串列表进行寻址"$@"
,这意味着您可以执行以下操作:
md5sum -- "$@"
...因为您显然正在寻找有用的交互式速记:
alias rdcb='
[ -t 0 ] && set -- &&
while IFS= read -r in
do set -- "$@" "$in"
done'
...将定义一个alias
可以在交互式 shell 中运行的命令,以将 shell 的参数设置为来自标准输入的换行符分隔数组。
所以...
{ ls -1 | xsel -bi #pipes ls output into my clipboard
rdcb #terminal hangs, shift+insert && crtl+d
xsel -bo #writes my clipboard to stdout
printf %s\\n '' --- '' "$@" #writes \n-delimited shell arg array
printf %s\\n '' --- '' "$3" "$5" #writes only args "$3" and "$5"
}
1
edit.sh
paccache
sh
systemd-private-75115542eb544b09bc245e8ca7765854-systemd-timesyncd.service-CKruFk
sztally
yaourt-tmp-mikeserv
---
1
edit.sh
paccache
sh
systemd-private-75115542eb544b09bc245e8ca7765854-systemd-timesyncd.service-CKruFk
sztally
yaourt-tmp-mikeserv
---
paccache
systemd-private-75115542eb544b09bc245e8ca7765854-systemd-timesyncd.service-CKruFk
这是一个更好的版本:
alias rdcb='
if [ -t 0 ]
then set -f -- "$IFS" "${IFS+IFS=\$1;} set +f -$-
stty $(stty -g; stty raw -echo min 1 time 2)"
IFS=$(printf \\r)
set -- "$@" $(dd bs=4k count=1 2>/dev/null)
eval "unset IFS;$2;shift 2"
fi '
它放弃了终端回显和终端特殊字符处理,并且不需要CTRL+D表示输入结束。它所做的所有事情都是临时的,并且它会小心地将它影响的所有设置恢复到完成时发现它们的状态,除了 shell 的参数,当然,这些参数是根据设计而永久更改的。
因此,您只需执行此操作rdcb
,然后粘贴即可完成。当您粘贴时,屏幕上不会有任何输出 - 终端将挂起,然后您在十分之一秒内输入至少一个字节,提示将重新出现。之后,您可以像以前一样处理参数。