
ファイルマネージャでは、通常、ファイルを選択し、他のShiftファイルを長く選択できます。その間のすべてのファイルが選択されます。
私はしたいbash
/zsh
これと同等である。
例:2つのファイル名を指定したいと思います。各ファイル名は中央にあります(アルファベット順 -ls
出力方式)。
そして他のワイルドカードオプションを知っていますが、名前が? {} *
非常に混乱しているファイルに使用できることを願っています。
たとえば、与えられたファイル
$ ls
aoeitoae.txt
oaeistn.txt
oaie.txt
paeoai.txt
sotaoe.txt
次のコマンドを実行して次のようにしますrm aoeitoae.txt-oaie.txt
。
$ ls
paeoai.txt
sotaoe.txt
この目標をどのように達成できますか?
答え1
この答えは主にzshについてです。ほとんどの操作はbashでは簡単にはできません。
多くの一般的な状況で使用できます。ワイルドカード。特に:
- すべてが付属固定プレフィックス:
foo-*
- すべてが付属固定プレフィックスの後に範囲内の他の文字が続きます。:(、、、を
foo[b-m]*
含むが、または除く)foobar
food
foomz1
fooar
foon
- 特定の範囲内の数:(
IMG-<7-42>.*
含むIMG-8.PNG
とIMG-0042.JPG
除くIMG-77.JPG
)
そしてグローバル予選、識別する簡単な方法があります。範囲ですが、数が必要です:ファイルが何であれ、リストされてfoo*([1,3])
いる最初の3つのファイルと一致しますfoo*
(3つ未満の場合はすべてのファイルと一致します)。foo*(om[1,3])
これは、で始まる名前の一致などのソートが完了した後に発生しますfoo
。
zshに数字を調べるように依頼できます。 2つのステップで行います。まず、すべての一致を配列に配置し、次を使用します。下付き文字記号 i
(ワイルドカードの一致を防ぐI
場合e
):要素間の配列部分(含まれて$a[$a[(i)foo],$a[(I)bar]]
いる)または存在しない場合は空です。$a
foo
bar
foo
bar
a=(*.txt(oL))
# List the files that appear between small.txt and large.txt in a listing by size.
# Note that files that have the same size as one of the bounds may or may not be included.
echo $a[$a[(I)small.txt],$a[(I)large.txt]]
だからこれは実装する関数です。質問の要件を完全に満たしています。(正確な構文を除いてこれを行うことはできません):
# Usage: select_range FROM TO WILDCARD_PATTERN
# Sets the array $s to the files matching PATTERN from FROM to TO inclusive.
function select_range {
if (($# < 2)); then
echo >&2 "select_range: missing range arguments"
return 120
fi
local from=$1 to=$2
shift 2
from=$@[(ie)$from]
if ((from == 0)); then
echo >&2 "select_range: not matched: $from"
fi
to=$@[(Ie)$to]
if ((to == 0)); then
echo >&2 "select_range: not matched: $from"
fi
s=($@[$from,$to])
}
使用法:select_range aoeitoae.txt oaie.txt * && rm $s
globe
修飾子を使用すると、任意のコードを書いて結果をフィルタリングできますが、少し扱いにくくなり始めました。複雑なケースでは、引用は難しいかもしれません。簡略化のために'
区切り記号(バックスラッシュとして引用する必要があります)として使用し、フィルタコードを一重引用符で囲んでパターンを次に示しますfoo-*(e\''code goes here'\')
。 (引用が複雑すぎる場合は、関数を作成して修飾子を使用してください+
。)フィルタリングaoeitoae.txt
前とフィルタリング前のファイルoaie.txt
アルファベット順:*(e\''! [[ $REPLY < aoeitoae.txt || $REPLY > oaie.txt ]]'\')
。
フィルタで実行された比較は、必ずしもワイルドカード拡張と同じ順序を使用するわけではありません。たとえば、thanks修飾子はfoo-*(n)
前にリストされていますが、文字列比較ではfoo-9
foo-10
n
[[ foo-9 > foo-10 ]]
ホームフレーズ整数部分文字列の数値比較に似た>
演算子です。一つ作りたいなら文字列と数値でソートされた整数部分の比較、あなたはそれを使用することができますn
パラメータ拡張フラグ配列を並べ替え、中間に一致する名前が保持されていることを確認します。 、、、、...*(ne\''a=(b11r $REPLY f10o); [[ $a[2] == "${${(@n)a}[2]}" ]]'\'))
は含まれていますが、、、...は含まれていません。b101r
b11s
d1
f02o
b9r
f011
日付別にファイルを一致させる場合は、条件を使用できます(ファイルは独自のファイル-nt
よりも最新ではありません)。*(ome\''! [[ $REPLY -ot from || $REPLY -nt to ]]'\')
間に修正されたファイルの修正時間from
との修正時間to
(含む)です。
答え2
Bash機能を使う:
sfiles ()
(
# run this in a subshell, so we don't have to care if nullglob/dotglob were enabled or not
[ $# -eq 0 ] && exit
local nullsep=0
if [ "$1" = "-0" ]; then
nullsep=1; shift
fi
local first=$1
shift $(($# -1))
local last=$1
local files=( )
shopt -s nullglob dotglob
for i in *; do
# first argument found or array not empty?
if [ "$i" = "$first" ] || [ "${#files[@]}" -ne 0 ]; then
files+=( "$i" )
fi
# last argument found? break loop
[ "$i" = "$last" ] && break
done
if [ "${#files[@]}" -gt 0 ]; then
[ "$nullsep" -eq 1 ] &&
printf '%s\0' "${files[@]}" ||
printf '%s\n' "${files[@]@Q}"
fi
)
最初の引数と最後の引数(含む)の間のすべてのファイルを出力します。
例:
$ ls -A
btjhyyxrlv.txt otewagahzp.txt .xxx
crlcsbzizl.txt ssffszhdmp.txt 'zdjtgahx q.txt'
hgiagchkgt.txt 'tt'$'\t''aa.txt' 'zmwik zhur.txt'
jusupbivit.txt umikyfucgu.txt 'z otmleqlq.txt'
' kcyigyurc.txt' ' upvpntdfv.txt' .zzz
kfthnpgrxm.txt 'uu'$'\t\t''aa.txt'
lgzsmquxwj.txt wlwexgzohs.txt
$ sfiles c* k*
'crlcsbzizl.txt'
'hgiagchkgt.txt'
'jusupbivit.txt'
' kcyigyurc.txt'
'kfthnpgrxm.txt'
$ sfiles .xxx .zzz
'.xxx'
'zdjtgahx q.txt'
'zmwik zhur.txt'
'z otmleqlq.txt'
'.zzz'
$ LC_ALL=C sfiles .xxx .zzz
'.xxx'
'.zzz'
無効な順序です。何も返しません。
$ sfiles .zzz .xxx
選択したファイルを削除するには、次のコマンドを使用しますxargs
。
$ sfiles .xxx .zzz | xargs rm
タブまたは改行を含むファイル名の場合は、-0
bash引用符なしでnullで区切られた出力の最初の引数としてオプションを追加します。
$ sfiles -0 tt* uu* | xargs -0 ls
'tt'$'\t''aa.txt' ' upvpntdfv.txt'
umikyfucgu.txt 'uu'$'\t\t''aa.txt'
答え3
これを行うには、独自のシェル関数を作成できます。すべてのファイルのリストを取得し、最初のファイル名の前のすべてのファイルと2番目のファイル名の後のすべてのファイルを削除します。おおまかに言えば、zshはこれがbashでもっと迷惑になると思うからです。
#!/usr/bin/zsh
filerange() {
# variable "reply" is an array
typeset -ag reply
reply=("$1")
# don't get upset if nothing matches
setopt nullglob
# get a complete list of candidate files
#allfiles=*(^/^on)
# ^--------- * glob
# ^----^--- (…) glob modifiers within parentheses
# ^------- ^ invert match
# ^------ / match directories (inverted: match all *but* dirs)
# ^----- ^ invert sort order (uninvert the above inversion)
# ^---- o order by:
# ^--- n character values of name
for fname in *(on^/); do
[[ ( "$2" > "${fname}" && "${fname}" > "$1" ) ]] \
&& reply+=("${fname}")
done
reply+=("$2")
}
$reply
これは、たとえば、使用できる素敵で「安全な」配列を提供しますfor
。
# prepare a test dir
mkdir /tmp/testdir
cd /tmp/testdir
sudo mknod blockdev b 1 1
sudo mknod chardev c 1 1
mkdir dir
mkfifo fifo
touch file
touch "file with spaces"
touch "file with\nnewlines"
touch "last file"
touch "ok one more file"
ln -s blockdev symlink
# This will look funny, because there's a file name with a new line in there
echo *
# Let's try this:
filerange chardev "last file"
# We're expecting to get all files from (incl) chardev to (incl) last file,
# but not `dir`, as that's a directory
for f in ${reply}; do;
echo "entry: ${f}"
done
parallel
もちろん、これらのファイル(forやなど)を印刷したい場合は、Freddyのファイルとしてオプションを使用する関数を作成してくださいxargs
。-0
良い答えイラストは抜群の選択です!この関数はとても簡単です。 'ingループから呼び出すことができ、fromをfilerange
処理します。$reply
printf
for
答え4
これは完全な答えではありませんが、awk
使用できる優れた範囲演算子があることに言及したかったです。
$ ls | awk '/^aoeitoae\.txt$/,/^oaie\.txt$/ { print }'
aoeitoae.txt
oaeistn.txt
oaie.txt
このawk
コードは、最初の正規表現に一致する最初の入力行から始まり、2番目の正規表現に一致する最初の入力行で終わる入力行を印刷します。
マッチングは正規表現を使用し、この例では引用されていないため、ファイル名にスペースやその他の奇妙な文字が含まれているため、予期しない結果が生じる可能性があります。
そしておそらく次のテキストベースのファイルマネージャを試してみたいです。真夜中司令官。