
私は初めてbashに触れました。簡単なコマンドを使用して、一度に1つの簡単な管理タスクを実行できます。しかし、私はテキストファイルを名前変更ソースとして使用してディレクトリ内のいくつかのファイル名を変更するという任務を担当しており、私の能力をはるかに超えているので、いくつかのアドバイスに本当に感謝しています。
説明します。
New File Name.xlsx 0.1 000011F4.dat
New File Name.xlsx 0.2 000011F5.dat
New File Name.xlsx 0.3 000011F6.dat
New File Name.xlsx 0.4 000011F7.dat
New File Name.xlsx 0.5 000011F8.dat
New File Name.xlsx 0.6 000011F9.dat
私のソーステキストファイルは上記と似ています。目的は、最初の「列」がファイルの新しい名前、中間がバージョン、3番目の列が現在のファイル名であることです。
ディレクトリ内の.datファイルの名前を最初の列に表示されている名前に変更する必要があります。また、各ファイルの先頭にバージョン番号0.1、0.2などを追加する必要があります。
いくつかの質問があります。
ファイルにスペースがあるのは大きな問題ですか?各ファイル文字列の周りに ""を追加する方が良いですか?
基本的にどこから始めるべきかわかりません。助けてくれてありがとう。ご覧のとおり、ファイル名の先頭にバージョン列を追加し、リストにスペースを追加する必要がある一般的な名前変更よりも少し複雑です。
答え1
これは働きます:
sh <(sed -r 's/^\s*(.*)\s+([0-9\.]+)\s+([0-9A-Z]{8}\.dat)\s*$/mv -iv \3 "\2 \1"/' files)
...files
ソースファイルの名前がある場所です。
これは、次のようにコマンドの結果をsed
(シェル)の新しいインスタンスに渡すことです。sh
プロセスの交換。このコマンドの出力は次のsed
とおりです。
mv -iv 000011F4.dat "0.1 New File Name.xlsx"
mv -iv 000011F5.dat "0.2 New File Name.xlsx"
mv -iv 000011F6.dat "0.3 New File Name.xlsx"
mv -iv 000011F7.dat "0.4 New File Name.xlsx"
mv -iv 000011F8.dat "0.5 New File Name.xlsx"
mv -iv 000011F9.dat "0.6 New File Name.xlsx"
このsed
コマンドを分析してパターンを検索します。
^
- 行の始まり\s*
- 最初にスペースがある場合(.*)
- すべての文字(結果は括弧内に保存されます\1
)\s+
- 少なくとも1つの空白文字([0-9\.]+)
0-9
- と1つ以上.
(に保存\2
)\s+
- 少なくとも1つの空白文字([0-9A-Z]{8}\.dat)
0-9
A-Z
- 中やそれに続く8文字.dat
(に保存\3
)\s*
- 最後にスペースがある場合$
- 行末
...これをに置き換えますmv -iv \3 "\2 \1"
。ここで、 \1
to\3
は以前に保存された値です。必要に応じて、バージョン番号とファイル名の残りの部分の間にスペース以外のものを使用できます。
結果は次のとおりです。
$ ls -l
total 60
-rw-rw-r-- 1 z z 0 Aug 8 14:15 000011F4.dat
-rw-rw-r-- 1 z z 0 Aug 8 14:15 000011F5.dat
-rw-rw-r-- 1 z z 0 Aug 8 14:15 000011F6.dat
-rw-rw-r-- 1 z z 0 Aug 8 14:15 000011F7.dat
-rw-rw-r-- 1 z z 0 Aug 8 14:15 000011F8.dat
-rw-rw-r-- 1 z z 0 Aug 8 14:15 000011F9.dat
-rw-rw-r-- 1 z z 222 Aug 8 13:47 files
$ sh <(sed -r 's/^\s*(.*)\s+([0-9\.]+)\s+([0-9A-Z]{8}\.dat)\s*$/mv -iv \3 "\2 \1"/' files)
`000011F4.dat' -> `0.1 New File Name.xlsx'
`000011F5.dat' -> `0.2 New File Name.xlsx'
`000011F6.dat' -> `0.3 New File Name.xlsx'
`000011F7.dat' -> `0.4 New File Name.xlsx'
`000011F8.dat' -> `0.5 New File Name.xlsx'
`000011F9.dat' -> `0.6 New File Name.xlsx'
$ ls -l
total 60
-rw-rw-r-- 1 z z 0 Aug 8 14:15 0.1 New File Name.xlsx
-rw-rw-r-- 1 z z 0 Aug 8 14:15 0.2 New File Name.xlsx
-rw-rw-r-- 1 z z 0 Aug 8 14:15 0.3 New File Name.xlsx
-rw-rw-r-- 1 z z 0 Aug 8 14:15 0.4 New File Name.xlsx
-rw-rw-r-- 1 z z 0 Aug 8 14:15 0.5 New File Name.xlsx
-rw-rw-r-- 1 z z 0 Aug 8 14:15 0.6 New File Name.xlsx
-rw-rw-r-- 1 z z 222 Aug 8 13:47 files
答え2
sed 's/^\(.*\.xlsx\) \+\([[:digit:]]\+\.[[:digit:]]\+\) \+\(.[^ ]*\)/"\3" "\2\1"/' \
<file_list | xargs -n 2 mv
これにより、行が前の部分に分割されます.xlsx
。これは新しい名前の2番目の部分であり、経由でアクセスできます\1
。バージョンを取得して末尾の\2
スペースを無視し、古いファイル名を 。
これは参照され、パラメータmv
として提供されます。古いファイル名と新しいファイル名の2つのパラメータを-n 2
受け取る必要があります。mv
これらのスペースは何の問題も生じません。問題を複雑にするのは、入力リストの構造が間違っていることです。列と参照ファイルの名前を変更するには、あらかじめ実行せずにxargs
andを使用してくださいmv
。
答え3
ファイル名にスペースがあり、いくつかの列の間に複数のスペースを使用すると、これはより困難になりますが、決して克服できないわけではありません。
リストファイルを1行ずつ読みます。普通の人が使うようになるwhile IFS= read -r; do …
ただし、ここでは先行スペースと末尾のスペースを削除する方が強力です。各行に対して、次の操作を行います。
- 各行を3つの部分に分割します。 1つの方法は正規表現マッチングを使用することです。
[[:space:]]+
1つ以上のスペース文字(スペースまたはタブ)と一致します。[[:space:]]+
1 つ以上の空白以外の文字と一致します。BASH_REMATCH
括弧内のグループは変数で検索できます。
ここであまり便利ではない別の方法は、変数でそれぞれ接頭辞または接尾辞を使用または${VAR##PATTERN}
削除することです。${VAR%PATTERN}
- 最後に作業を行います。エラーを記録することを忘れないでください。
一緒に入れてください:
ret=0
while read line; do
if [[ $line =~ (.*[^[:space:]])[[:space:]]+([^[:space:]]+)[[:space:]]+([^[:space:]]+) ]]; then
new_name="${BASH_REMATCH[1]}"
version="${BASH_REMATCH[2]}"
old_name="${BASH_REMATCH[3]}"
mv -- "$old_name" "$version$new_name" || ret=1
else
echo "Malformed line: $line"
fi
done <name_list.txt
exit $ret
答え4
回避策は、awk
次のコマンドを実行することです。
awk '{print "/bin/mv", $NF, "\"" $(NF-1), gensub(/^([^.]+\.xlsx).*/, "\\1", 1) "\"" | "bash" } ; END { close("bash") }' sourcefile
前のコマンドはbash
コマンド出力をシェルにパイプします。
awk '{print "/bin/mv", $NF, "\"" $(NF-1), gensub(/^([^.]+\.xlsx).*/, "\\1", 1) "\""}' sourcefile
まず、それを実行して、実際に必要なタスクであることを確認する必要があります!このawk
コマンドはソースファイルの各行を印刷し/bin/mv
、行の最後のスペースで区切られたフィールド、二重引用符、行の最後から2番目のフィールドを順番に印刷し、行全体をEverythingに置き換えます.xlsx
。その後に二重引用符で囲まれた結果が表示されます。
以下はあなたが好むかもしれないバリエーションです。
awk '{print "/bin/mv", $NF, "\"" "0." FNR, gensub(/^([^.]+\.xlsx).*/, "\\1", 1) "\"" | "bash" } ; END { close("bash") }' sourcefile
変数FNR
は行番号です(したがって、ソースファイルから項目0.1、0.2、0.3、...を省略できます)。
ファイル名の空白は「大きな問題」とは呼ばれませんが、お勧めできません。新しいファイル名のスペースをアンダースコアに変更する最終バージョンのようなものを使用できます。
awk '{print "/bin/mv", $NF, "0." FNR "_" gensub(" ","_", "g", gensub(/^([^.]+\.xlsx).*/, "\\1", 1)) | "bash" } ; END { close("bash") }' sourcefile