に基づくファイルから派生した比較的小さいファイル名のリストがありますfind
。ファイル名にはスペースや句読点を含めることができますが、印刷できない文字や改行文字は確実に含まれていません。
例えば、
Netherlands/Purge (GDPR) 2020-01-09.txt
Netherlands/Purge (GDPR) 2020-01-27.txt
Switzerland/New mailing 2020-01-27.txt
部分的にファイル間を簡単に前後に移動できるように、このファイルをグループ(vi file1 file2 file3
代わりに)で編集したいと思います。vi file1; vi file2; vi file3
私はすでに始まっています生成されたファイル名のリストを引数リストとして使用 - スペースを含める
、標準的なfind -print0 | xargs -0 mycommand
解決策があります。残念ながら、mycommand
編集者が編集者の場合は機能しません。なぜなら、xargs
編集するファイルセットを集めることは可能ですが、標準入力すでにパイプラインからインポートされているため、エディタを所定の場所で実行する方法はありません。パイプ自体find -exec vi {} +
だけでなく、ファイル名のセットを検証するためにパイプを使用しているため、これはできませんfind
。
他のオプションは、コピーして貼り付け、ファイル名のリストを結合し、引用符で囲んでから結果を前に追加することですvi
。これら3つのファイルの場合、これは単純ですが、通常は簡単に再利用できるソリューションではありません。
vi 'Netherlands/Purge (GDPR) 2020-01-09.txt' 'Netherlands/Purge (GDPR) 2020-01-27.txt' 'Switzerland/New mailing 2020-01-27.txt'
私が好むシェルとしてGNU / Linuxプラットフォームがある場合bash
(重要であれば)、生成されたファイルのリストのようなものをどのように編集できますか?
答え1
Bashにいるから
#!/bin/bash
readarray -d '' -t files < <(find path -type f -print0)
vi -- "${files[@]}"
find path -type f -print0
実際のパイプと交換してください。
ファイルに改行文字がない場合でも、ユーザーはこれらのファイル名のサポートを追加しました。グレンジャックマン。
bufferの代わりにタブを使用するには、次のフラグをvi
追加します。-p
vi -p ...
配管が不要な場合は、このオプションを直接使用できます-exec
。
find path -type f -exec vi -- {} +
答え2
残念ながら、mycommandがエディタの場合は機能しません。なぜなら、xargsは編集するファイルセットを組み合わせることができますが、stdinはすでにパイプからインポートしてエディタを所定の場所で実行する方法を見ることができないからです。
このアプローチはGNU Findutilsのマニュアルページに文書化されていますxargs
。
-o, --open-tty
Reopen stdin as /dev/tty in the child process before executing
the command. This is useful if you want xargs to run an inter‐
active application.
この方法で使用できます
find . -name 'pattern' -print0 | xargs -0o vim
しかし、これは新機能です。 xargs 4.4.2を持つ古いシステムでは表示されません。 xargs 4.7.0を搭載したUbuntu 18では表示されます。
今は10年前と同じオプションがxargs
ないかもしれませんが、-o
Bashプロセスの置き換えは10年前に存在し、標準入力ではなくファイルから読み取るオプションがxargs
ありました。-a
したがって、この問題は解決される可能性があります。次のようにする必要はありませんxargs -o
。
xargs -0 -a <(find . -name 'pattern' -print0) vim
xargs
引数で受け取ったファイルを読み込んでいるので(思うように)標準入力を保持します。
答え3
私が得たコメントでは、以下はあなたの命令です。
find -type f -mtime +14 -mtime -22 -iname '*.xml' | while IFS= read -f x; do xmlstarlet sel -T -t -v '//magicElement' -n "$x" | grep -q magicValue && echo "$x"; done
while
-exec sh -c '...'
-loopにパイプするのではなく、パイプを使用してファイルをフィルタリングできます。
find -type f -mtime +14 -mtime -22 -iname '*.xml' \
-exec sh -c 'xmlstarlet sel -T -t -v "//magicElement" "$1" | grep -q magicValue' find-sh {} \; \
-exec vi -- {} +
努力する:
3つのファイルを考えてみましょう。
.
├── a:<magicElement>magicValue</magicElement>
├── b:<magicElement>magicValue</magicElement>
└── c:<magicElement>someOtherValue</magicElement>
$ find . -type f \
-exec sh -c 'xmlstarlet sel -T -t -v "//magicElement" "$1" | grep -q magicValue' find-sh {} \; \
-exec echo vi -- {} +
出力:
vi -- ./a ./b
答え4
私が長年にわたってこの問題を解決するために使用してきた2つの醜い方法は次のとおりです。どちらもXが必要です。
find ... -print0| ...| xargs -0r gvim -f
find ... -print0| ...| xargs -0r xterm -e vim
SSH経由でも動作します。