ls テキスト出力を操作してファイル名パスを追加する

ls テキスト出力を操作してファイル名パスを追加する

時には、次のls出力形式のファイルを取得します。

/etc/cron.d:
-rw-r--r-- 1 root root 128 May 15  2020 0hourly
-rw------- 1 root root 235 Dec 17  2020 sysstat
/etc/cron.daily:
-rw------- 1 root root 235 Dec 17  2020 sysstat

一般的なGnuツールを使用するか、bashの内部を削除してそれを操作する機会がありますか?

-rw-r--r-- 1 root root 128 May 15  2020 /etc/cron.d/0hourly
-rw------- 1 root root 235 Dec 17  2020 /etc/cron.d/sysstat
-rw------- 1 root root 235 Dec 17  2020 /etc/cron.daily/sysstat

素晴らしいです。

最も簡単な方法は、次のようにファイルパスを削除することです。 cat <filename> | grep -v -E "^\/[a-z]"

しかし、私が言ったように、このパスをファイル名の後続行にどのように移動できますか?

与えられたコマンドは次のとおりですls -lR /etc/cron* > <filename>

私はその出力には影響しませんが、lsによって実行されたこれらのコマンドの出力を<filename>私に送信される別のファイルにリダイレクトします。

私がやりたいことは、その内容を言及された2番目の結果に操作することです。デフォルトでは、最初の行をインポートしてファイルの2行目と3行目にパスを適用し、4行目をインポートして5行目に適用します。その後、これを一般的な方法で設定します。

awkを使うと効果があると思います。

答え1

ファイル名またはディレクトリ名にスペースが含まれていない場合は、POSIX awkを使用して次のことを実行できます。

$ awk '
    NF==1 && sub(/:$/,"/") { dir=$0; next }
    match($0,/[^[:space:]]+$/) { $0=substr($0,1,RSTART-1) dir substr($0,RSTART) }
    { print }
' file
-rw-r--r-- 1 root root 128 May 15  2020 /etc/cron.d/0hourly
-rw------- 1 root root 235 Dec 17  2020 /etc/cron.d/sysstat
-rw------- 1 root root 235 Dec 17  2020 /etc/cron.daily/sysstat

または、ファイル/ディレクトリ名にスペースを含めることができますが、ディレクトリパスが常に次から始まり、出力に/常にlsファイル名の前にまったく同じ数のフィールドがある場合(例のように)、次のことができます。

$ awk '
    /^\// && sub(/:$/,"/") { dir=$0; next }
    match($0,/^([^[:space:]]+[[:space:]]+){8}/) { $0=substr($0,1,RLENGTH) dir substr($0,RLENGTH+1) }
    { print }
' file

ただしls、これらのフィールドを使用して出力を生成することは必ずしも可能ではありません(ls日付/時刻出力はファイルの寿命とロケールによって異なり、たとえばユーザーIDにスペースを含めることができます)、各ファイル行のすべての文字が表示されることがありますあります。ファイル名とディレクトリ名には:YMMVを除く任意の文字を含めることができるため、ディレクトリ名はユーザーが思う/ように終了できます。NUL行を区別し、各ファイル行でファイル名を見つけます。さらに、ファイル名に改行文字を含めることができます。これはまったく別の問題です。

lsしたがって、生成できるすべての可能な出力を解析する信頼できる方法はありません。これを行うには、呼び出すコンテキストに関係なく十分だと思うか、必要なパターンマッチングが何であるかを把握し、それに基づいてスクリプトをls作成します。

一部の他のツールはls解析する必要がある出力ファイルを生成するため、解析を試みるべきではないことを私たち全員が知っているので、他のツールを修正する必要がありますls(参照http://mywiki.wooledge.org/ParsingLsそしてなぜ`ls`を解析しないのですか*(そしてどうすればいいですか?))したがって、このツールは失敗します。

答え2

使用しているコマンドまたはこの出力が表示される理由を示していないが、目標が一致するすべてのファイルとディレクトリを一覧表示する場合は、/etc/cron*代わりに次のように使用できますfind

find /etc/cron*

または完全なリストが必要な場合(GNU find):

find /etc/cron* -ls

どのfind:

find /etc/cron* -exec ls -ld {} +

私のArch Linuxの出力例は次のとおりです。

$ ls /etc/cron*
/etc/cron.deny  /etc/crontab  /etc/crontab~  /etc/crontab.pacnew

/etc/cron.d:
0hourly

/etc/cron.daily:

/etc/cron.hourly:
0anacron

/etc/cron.monthly:

/etc/cron.weekly:

そしてfind

$ find /etc/cron* -ls
   262172      4 drwxr-xr-x   2 root     root         4096 Jan 23 19:41 /etc/cron.d
   263666      4 -rw-r--r--   1 root     root          128 Jan 14 14:59 /etc/cron.d/0hourly
   262173      4 drwxr-xr-x   2 root     root         4096 Sep 30 11:38 /etc/cron.daily
   262618      4 -rw-r--r--   1 root     root           74 Jan 14 14:59 /etc/cron.deny
   262174      4 drwxr-xr-x   2 root     root         4096 Jan 23 19:41 /etc/cron.hourly
   263665      4 -rwxr-xr-x   1 root     root          843 Jan 14 14:59 /etc/cron.hourly/0anacron
   262175      4 drwxr-xr-x   2 root     root         4096 Jun 30  2016 /etc/cron.monthly
   262632      0 -rw-r--r--   1 root     root            0 Oct 31  2017 /etc/crontab
   262633      4 -rw-r--r--   1 root     root           49 Sep 22  2017 /etc/crontab~
   272465      4 -rw-r--r--   1 root     root          119 Jan 14 14:59 /etc/crontab.pacnew
   262176      4 drwxr-xr-x   2 root     root         4096 Sep 30 11:38 /etc/cron.weekly
   275802      4 -rwxr--r--   1 root     root           68 Sep 30 11:37 /etc/cron.weekly/clamscan.sh

答え3

ソリューションTXR不明瞭な音声

lsこの出力をどこかから取得し、それを使用する必要があるという事実を当然に考えてください。元の時間と機械に戻って他の形式で情報を取得することはできません。

$ txr lsdata.tl < lsdata
-rw-r--r-- 1 root root 128 May 15  2020 /etc/cron.d/0hourly
-rw------- 1 root root 235 Dec 17  2020 /etc/cron.d/sysstat
-rw------- 1 root root 235 Dec 17  2020 /etc/cron.daily/sysstat

どこlsdata.tl

(let ((curdir ""))
  (whilet ((line (get-line)))
    (match-case line
      (`@dir:` (set curdir dir))
      (`@{metadata 39} @name` (put-line `@metadata @curdir/@name`)))))

完璧ではありません。で終わる名前でだまされます:。ディレクトリ行領域が常に絶対パスであると仮定できる場合は、それを一致に含めることができます。

(let ((curdir ""))
  (whilet ((line (get-line)))
    (match-case line
      (`/@dir:` (set curdir dir))
      (`@{metadata 39} @name` (put-line `@metadata /@curdir/@name`)))))

答え4

何が欲しいのかわかりませんが、次のコマンドを試してください。

$ ls -la | awk -v path=$PWD '{$NF=path"\/"$NF;print}' |sed 's| /| \t/|g'

ルートの並べ替えに興味がない場合は、sed部分を削除できます。

関連情報