# How to both show a list of files and a \`cat\` of one

**URL:** <https://discourse.nodered.org/t/how-to-both-show-a-list-of-files-and-a-cat-of-one/100339>\
**Category:** General\
**Created:** [7 February 2026 22:07 UTC](https://discourse.nodered.org/t/how-to-both-show-a-list-of-files-and-a-cat-of-one/100339 "2026-02-07T22:07:04Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [7 February 2026 22:07 UTC](https://discourse.nodered.org/t/how-to-both-show-a-list-of-files-and-a-cat-of-one/100339/1 "2026-02-07T22:07:04Z")

</div>

Sorry folks. The brain is on holiday just now. 😉

I am stuck at the concept stage of the problem.

If a machine reboots (monthly) it creates a backup of the log file (and time stamps it at _NOW_ then starts a new log file.

Existing:  
I get a list of files in that directory. Not exciting and this is a nominal view:

 ![Screenshot from 2026-02-08 09-01-06](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/e/6e9af93b6f726cb496dbf7b2ae78adf32f39d94b.png)

As said: not exciting.  
But if other reboots happened to occur this month, they would be show with _time stamped_ file names. Which would indicate when the machine had rebooted.

_PROBLEM_ - as I see it.  
The `last_alive.db` file.  
That is an overwritten file showing the uptime.  
So I'm wanting to get that file's contents shown rather than it's name.  
ie:

```auto
cat last_alive.db 
HEARTBEAT
up 19 weeks, 6 days, 13 hours, 33 minutes

```

So the last (shown) line is the one I want to get/see.

I'm guessing it is not going to be easy.

Example of other months

```auto
pi@BedPi:/media/pi/06BB-C87D/logs/reboot/2025-06 $ ls
'Rebooted at 2025-06-04 175552.db' 'Rebooted at 2025-06-09 101721.db'
'Rebooted at 2025-06-04 225056.db' 'Rebooted at 2025-06-09 102751.db'
'Rebooted at 2025-06-04 234148.db' 'Rebooted at 2025-06-09 104929.db'
'Rebooted at 2025-06-05 202521.db' 'Rebooted at 2025-06-09 115023.db'
'Rebooted at 2025-06-06 180203.db' 'Rebooted at 2025-06-09 185031.db'
'Rebooted at 2025-06-06 183946.db' 'Rebooted at 2025-06-12 144016.db'
'Rebooted at 2025-06-07 070837.db' 'Rebooted at 2025-06-12 144153.db'
'Rebooted at 2025-06-08 182600.db' 'Rebooted at 2025-06-12 151600.db'
'Rebooted at 2025-06-08 191137.db'

```

So in/on that month I would get/see those file NAMES listed, and at the top the current last line of the `last_alive.db` file.

Thoughts?

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [7 February 2026 22:31 UTC](https://discourse.nodered.org/t/how-to-both-show-a-list-of-files-and-a-cat-of-one/100339/2 "2026-02-07T22:31:12Z")

</div>

> [@Trying\_to\_learn](#):
>
> So the last (shown) line is the one I want to get/see.
> 
> I'm guessing it is not going to be easy.

Off the top of my head and completely untested ...

Read in the whole file as a string. Split the string on `/n` (linefeed character). Now you have an array. Throw away the first line (`arrayvar.splice(1)`?). Use `arrayvar.replace` to get rid of fixed text and use `arrayvar.split(', ')` to get a new array with values. You could do all that with a single regex if you prefer.

For the rest, I'd use an `ls` output - or, better use a filing system node or add `node:fs` as a package to a function node and use node.js's fs tools. You just need a list of the file names and then extract the date/time.

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [7 February 2026 22:32 UTC](https://discourse.nodered.org/t/how-to-both-show-a-list-of-files-and-a-cat-of-one/100339/3 "2026-02-07T22:32:58Z")

</div>

THANKS!

That is the idea which kinda came into my head.

Working on it with _Mr ChatGPT_ just now.

---

<div class="post-metadata">

**Author:** ![jbudd](https://avatars.discourse-cdn.com/v4/letter/j/5f8ce5/32.png) [@jbudd](https://discourse.nodered.org/u/jbudd)\
**Post date:** [8 February 2026 10:02 UTC](https://discourse.nodered.org/t/how-to-both-show-a-list-of-files-and-a-cat-of-one/100339/4 "2026-02-08T10:02:52Z")

</div>

> [@Trying\_to\_learn](#):
>
> Thoughts?

Well...  
You want (a) the last line of the most recent file _in that directory_ 2025-06?  
Or you want (b) the last line of the most recent file _in any directory below_ /media/pi/06BB-C87D/logs/reboot?

You made your life harder by including spaces in your filenames!  
It looks like directory and file names can be sorted in date order.

Does `find /media/pi/06BB-C87D/logs/reboot -name "Rebooted at*" -print | sort | tail -1` give you the name of the most recent log file?

If so, the last line in that file should be given by `tail -1 $(find /media/pi/06BB-C87D/logs/reboot -name "Rebooted at*" -print | sort | tail -1)`

---

<div class="post-metadata">

**Author:** ![jbudd](https://avatars.discourse-cdn.com/v4/letter/j/5f8ce5/32.png) [@jbudd](https://discourse.nodered.org/u/jbudd)\
**Post date:** [8 February 2026 10:15 UTC](https://discourse.nodered.org/t/how-to-both-show-a-list-of-files-and-a-cat-of-one/100339/5 "2026-02-08T10:15:10Z")

</div>

I guess I should also ask what this whole palaver gives you.  
Is the output of `uptime --since` useful?

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [8 February 2026 10:15 UTC](https://discourse.nodered.org/t/how-to-both-show-a-list-of-files-and-a-cat-of-one/100339/6 "2026-02-08T10:15:14Z")

</div>

This is what "we" (_Mr GPT and I_) got after a LOT of messing around.

It got into hallucination mode and went around quite a number of times with the same reply.

Then I started to better understand what it was TRYING to do and tried a few things myself.

Sorry, this code has a path set for my TEST case but is easily modified.

Code - no foreigners in it.

```auto
[{"id":"5eea7184f98a4c51","type":"exec","z":"e891eac8.28aea8","command":"","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"List reboot files (newest first)","x":640,"y":2830,"wires":[["ac0cc1d229a3949c"],[],[]]},{"id":"f8c34d36176bb3de","type":"template","z":"e891eac8.28aea8","name":"cmd","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"find {{{basePath}}} -maxdepth 1 -type f ! -name 'last_alive.db' -printf '%f\\n' | sort -r","output":"str","x":430,"y":2830,"wires":[["9521311b0c077153","5eea7184f98a4c51"]]},{"id":"ac0cc1d229a3949c","type":"function","z":"e891eac8.28aea8","name":"Tag reboot file","func":"// Tag reboot file lines and prepare for merging\n\n// split payload into lines, trim whitespace, remove empty lines\nlet lines = msg.payload.split(/\\r?\\n/).map(l => l.trim()).filter(l => l !== '')\n\n// prepend 'Rebooted at ' only if not already present\nlines = lines.map(l => l.startsWith('Rebooted at') ? l : `Rebooted at ${l}`)\n\n// rejoin lines into single payload\nmsg.payload = lines.join('\\n')\n\n// mark this message as order 1 (after uptime)\nmsg.order = 1\n\n// if no lines left, mark as empty so Merge node can skip it\nif (lines.length === 0) {\n msg._emptyForMerge = true\n}\n\nreturn msg\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":880,"y":2830,"wires":[["018e232e3d83ec77","5219da2fc0395841"]]},{"id":"ed5f05a749fdb98b","type":"junction","z":"e891eac8.28aea8","x":310,"y":2860,"wires":[["f8c34d36176bb3de","45b84c6df27ea117","c53daecf90b70618"]]},{"id":"9521311b0c077153","type":"debug","z":"e891eac8.28aea8","name":"debug 18","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":580,"y":2780,"wires":[]},{"id":"018e232e3d83ec77","type":"function","z":"e891eac8.28aea8","name":"Merge last_alive + reboots","func":"// --- Explicit context wipe ---\nif (msg.wipe === true) {\n context.set('store', {})\n node.warn('Context wiped via msg.wipe')\n return null\n}\n\n// --- Get or initialise context store ---\nlet store = context.get('store') || {}\n\n// --- Require valid order ---\nif (msg.order !== 0 && msg.order !== 1) {\n node.warn('Invalid or missing msg.order')\n return null\n}\n\n// --- Store message by order (arrival order irrelevant) ---\nstore[msg.order] = RED.util.cloneMessage(msg)\ncontext.set('store', store)\n\n// --- Wait until both messages are present ---\nif (!store[0] || !store[1]) {\n return null\n}\n\n// --- Prepare output messages ---\nconst msg0 = RED.util.cloneMessage(store[0])\nconst msg1 = RED.util.cloneMessage(store[1])\n\nmsg0.topic = 'uptime_and_reboots'\nmsg1.topic = 'uptime_and_reboots'\n\n// --- Send BOTH messages from ONE output ---\nnode.warn('Sending msg.order 0 then msg.order 1')\nreturn [[msg0, msg1]]\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1120,"y":2860,"wires":[["9f41501f4fbd6cb7"]]},{"id":"5219da2fc0395841","type":"debug","z":"e891eac8.28aea8","name":"msg1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":910,"y":2790,"wires":[]},{"id":"378e0fe5313bc482","type":"change","z":"e891eac8.28aea8","name":"","rules":[{"t":"set","p":"basePath","pt":"msg","to":"/media/pi/06BB-C87D/logs/reboot/2025-06/","tot":"str"},{"t":"delete","p":"payload","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":200,"y":2860,"wires":[["ed5f05a749fdb98b"]]},{"id":"45b84c6df27ea117","type":"template","z":"e891eac8.28aea8","name":"file","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{{{basePath}}}last_alive.db","output":"str","x":430,"y":2890,"wires":[["a06b52bf2cd0ada2","5d69e6136bd43607"]]},{"id":"c53daecf90b70618","type":"debug","z":"e891eac8.28aea8","name":"base path","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"basePath","targetType":"msg","statusVal":"","statusType":"auto","x":340,"y":2940,"wires":[]},{"id":"aa1cd627e0d32f80","type":"function","z":"e891eac8.28aea8","name":"Extract uptime","func":"// extract line starting with 'up ' from last_alive.db\nconst lines = msg.payload.split(/\\r?\\n/)\nconst uptime = lines.find(l => l.startsWith('up '))\nmsg.payload = uptime || 'uptime not found'\nmsg.order = 0 // last_alive comes first\nreturn msg","outputs":1,"x":850,"y":2890,"wires":[["018e232e3d83ec77","3b146b0e65398225"]]},{"id":"b60a88c8903619e9","type":"inject","z":"e891eac8.28aea8","name":"Wipe","props":[{"p":"wipe","v":"true","vt":"bool"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":890,"y":2990,"wires":[["018e232e3d83ec77"]]},{"id":"9f41501f4fbd6cb7","type":"debug","z":"e891eac8.28aea8","name":"Final output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1080,"y":2920,"wires":[]},{"id":"09e98bbe33888ffa","type":"inject","z":"e891eac8.28aea8","name":"Trigger","props":[{"p":"basePath","v":"/media/pi/06BB-C87D/logs/reboot/2025-06/","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":190,"y":2810,"wires":[["378e0fe5313bc482"]]},{"id":"a06b52bf2cd0ada2","type":"file in","z":"e891eac8.28aea8","name":"Read last_alive.db","filename":"payload","filenameType":"msg","format":"utf8","chunk":false,"sendError":false,"encoding":"utf8","allProps":false,"x":610,"y":2890,"wires":[["aa1cd627e0d32f80"]]},{"id":"5d69e6136bd43607","type":"debug","z":"e891eac8.28aea8","name":"last alive","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":580,"y":2930,"wires":[]},{"id":"3b146b0e65398225","type":"debug","z":"e891eac8.28aea8","name":"msg2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":880,"y":2930,"wires":[]}]

```

# NEEDED files:

`last_alive.db` is the current active file which shows the uptime.  
Other files (which may or not exist) are any other files which were renamed if the machinereboots in THIS MONTH ONLY.  
At the start of each month, all existing files are moved to their respective month directories. (Or is it just before the end of the month? Does it matter?)

The output is then sent to a `ring buffer` node and I hope all are on their own line.

The only catch is the sorting of the other files and getting them to be _NEWEST AT THE TOP_ sorting.  
So the current (active) is at the top, then a list of all reboots for this month are shown below starting with the most recent to the oldest (at the bottom).

I spent about 3 hours (maybe more) today earlier and got it to this.

This is what I have in my `test directory` (as per the code)  
Files:

```auto
 last_alive.db 'Rebooted at 2025-06-08 191137.db'
'Rebooted at 2025-06-04 175552.db' 'Rebooted at 2025-06-09 101721.db'
'Rebooted at 2025-06-04 225056.db' 'Rebooted at 2025-06-09 102751.db'
'Rebooted at 2025-06-04 234148.db' 'Rebooted at 2025-06-09 104929.db'
'Rebooted at 2025-06-05 202521.db' 'Rebooted at 2025-06-09 115023.db'
'Rebooted at 2025-06-06 180203.db' 'Rebooted at 2025-06-09 185031.db'
'Rebooted at 2025-06-06 183946.db' 'Rebooted at 2025-06-12 144016.db'
'Rebooted at 2025-06-07 070837.db' 'Rebooted at 2025-06-12 144153.db'
'Rebooted at 2025-06-08 182600.db' 'Rebooted at 2025-06-12 151600.db'

```

The `last_alive.db` is a copy of the real one. But as it is needed, I had to put it there.

Basic structure:

```auto
cat Rebooted\ at\ 2025-06-04\ 175552.db 
2025-06-04 17:53:05
up 35 weeks, 5 days, 22 hours

```

and

```auto
cat last_alive.db 
HEARTBEAT
up 19 weeks, 6 days, 13 hours, 46 minutes

```

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [8 February 2026 10:17 UTC](https://discourse.nodered.org/t/how-to-both-show-a-list-of-files-and-a-cat-of-one/100339/7 "2026-02-08T10:17:34Z")

</div>

In reply to the last question:  
This is what I get for this example.  
Two messages:

```auto
up 19 weeks, 6 days, 13 hours, 46 minutes

```

And - needs work.

```auto
Rebooted at 2025-06-12 151600.db
Rebooted at 2025-06-12 144153.db
Rebooted at 2025-06-12 144016.db
Rebooted at 2025-06-09 185031.db
Rebooted at 2025-06-09 115023.db
Rebooted at 2025-06-09 104929.db
Rebooted at 2025-06-09 102751.db
Rebooted at 2025-06-09 101721.db
Rebooted at 2025-06-08 191137.db
Rebooted at 2025-06-08 182600.db
Rebooted at 2025-06-07 070837.db
Rebooted at 2025-06-06 183946.db
Rebooted at 2025-06-06 180203.db
Rebooted at 2025-06-05 202521.db
Rebooted at 2025-06-04 234148.db
Rebooted at 2025-06-04 225056.db
Rebooted at 2025-06-04 175552.db

```

Ideally each of those should be individual messages.  
But at this stage: not critical.

Then they are displayed on/in a table on the `dashboard`.

(Example of what I want)

 ![Screenshot from 2026-02-08 21-18-24](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/7/b72ed304f8d3788dbe4436e960bc9e6156fee536.jpeg)

But in this machine's case there is/was only 1 reboot this month.  
So it looks ok.  
I'd prefer it to be like the `commands received` list.  
Each entry in/on it's own line.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [8 February 2026 11:42 UTC](https://discourse.nodered.org/t/how-to-both-show-a-list-of-files-and-a-cat-of-one/100339/8 "2026-02-08T11:42:28Z")

</div>

Is the command  
`journalctl --list-boots --no-pager`  
any use to you?

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [8 February 2026 19:17 UTC](https://discourse.nodered.org/t/how-to-both-show-a-list-of-files-and-a-cat-of-one/100339/9 "2026-02-08T19:17:42Z")

</div>

Never even heard of that one.

I'll look into it.

```auto
pi@TelePi:~ $ journalctl --list-boots --no-pager
 0 e38adcfae09042a9b43c0bb79323f049 Sun 2026-02-08 07:16:26 AEDT—Mon 2026-02-09 06:18:34 AEDT

```

Looking above, not sure what that is telling me.  
But below is what I'm told with my system.

 ![Screenshot from 2026-02-09 06-20-49](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/3/3/33b90f73bb9e0160b071721002d28012c8699f00.png)

```auto
pi@BedPi:~ $ journalctl --list-boots --no-pager
 0 1de0c2c6667f44febb74e5b9eb484e65 Sat 2026-02-07 22:58:01 AEDT—Mon 2026-02-09 06:19:06 AEDT

```

On this machine, it is different but I seem to be given the same amount of information.

 ![Screenshot from 2026-02-09 06-24-07](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/0/f03573fe949c1381a8b0a6e588d7be1b2d0311cf.png)

So I'm not sure the command covers my needs in this case.

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [8 February 2026 20:57 UTC](https://discourse.nodered.org/t/how-to-both-show-a-list-of-files-and-a-cat-of-one/100339/10 "2026-02-08T20:57:55Z")

</div>

I think that the issue with `journalctl` is that logs are not necessarily persisted to files. On my system, like yours, the output is meaningless since my last reboot was at `2025-07-23T14:06:47`!!

For Debian systems at least, you can use the command

```bash
sudo utmpdump /var/log/wtmp | grep reboot

```

The raw output shows you not only boots but also all logins and some other stuff, hence the grep.

In theory, this file gets rotated periodically so I guess on a heavily used system, you might also have to check archived logs as well. On my system though, the first reboot entry is `2020-02-08T15:54:41` 🤣

This search may help if you do need to also review archives:

> **[How to decode /var/log/wtmp](https://search.brave.com/search?q=how+to+decode+%2Fvar%2Flog%2Fwtmp&summary=1&conversation=08b6f9f818469ca7b8b7934458c8a7f35089)**
>
> The \`/var/log/wtmp\` file is a binary log that records all user logins, logouts, and system reboots. It cannot be read directly with standard text editors or \`less\`.
> 
> \### Use \`utmpdump\` to decode the file
> The most reliable tool to decode \`wtmp\` is...

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [9 May 2026 20:58 UTC](https://discourse.nodered.org/t/how-to-both-show-a-list-of-files-and-a-cat-of-one/100339/11 "2026-05-09T20:58:35Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
