Find and remove all empty directories using the Linux command line

In order to find and remove all empty subdirectories in the current directory (.) recursively, use this command:

find . -depth -type d -print0 | xargs -0 rmdir

This command will only remove empty directories! Any file or non-empty directory won’t be modified.

Explanation of what the parts mean:

  • find: Use the find command to find directories recursively
  • .: Start recursing from the current directory. In case you want to start from a different directory, use that directory name here.
  • -type d: Only find directories – ignore files
  • -depth: Before printing a directory name, print all its sub-directory names. This avoids having to run this command repeatedly because the parent directory can’t be removed since its empty sub-directories need to be removed first
  • -print0 When printing all the directories that have been found, print a NUL character between directories. This is required in order to handle spaces in the directory names correctly
  • | xargs: Pipe the directories to xargs, a program that runs
  • -0: Split the input by NUL characters instead of newlines. This corresponds with the -print0 option to find and is required to handle spaces in directory names correctly.
  • rmdir: For each directory found, run rmdir i.e. try to remove the directory if it’s empty.
Posted by Uli Köhler in Linux

How to fix “OTGS Installer, responsible for receiving automated updates for WPML and Toolset, requires the following PHP component(s) in order to function:cURL” on Ubuntu 20.04

 Problem:

Your WordPress installation running on Ubuntu 20.04 shows you this error message:

OTGS Installer, responsible for receiving automated updates for WPML and Toolset, requires the following PHP component(s) in order to function:cURL

Learn more: Minimum WPML requirements

Solution:

You need to install the curl package for your PHP version.

Typically you can use

sudo apt -y install php7.4-curl

Doing this should immediately fix the issue (just reload your WordPress dashboard). In case you’re using PHP 7.2 you need to sudo apt -y install php7.2-curl instead.

In case the issue is still not fixed after doing this, try restarting your webserver (e.g. sudo service apache restart or sudo service nginx restart), try restarting PHP-FPM by using sudo service php7.4-fpm restart or sudo service php7.2-fpm restart or try rebooting your server. In case that doesn’t help either, you need to manually check which PHP instance the wordpress site is using and install the curl package for that PHP instance.

 

Posted by Uli Köhler in PHP, Wordpress

How to emulate Page up / Page down key in Puppeteer

To emulate a keypress to the Page up key in Puppeteer, use

await page.keyboard.press("PageUp");

To emulate a keypress to the Page down key in Puppeteer, use

await page.keyboard.press("PageDown");

 

Posted by Uli Köhler in Javascript, NodeJS, Puppeteer

How to run Nextcloud “php occ” in a docker-compose configuration

Use this command to run php occ inside a running docker Nextcloud container:

docker-compose exec -u www-data nextcloud php occ [command]

where:

  • nextcloud is the name of your container in docker-compose
  • -u www-data tells docker-compose to run the command as the www-data user that owns all the Nextcloud files.
  • Replace [command] by the php occ command you want to run, for example versions:cleanup. If you want to see a list of all available commands, just omit [command]

Note: You need to run this command in the directory where your nextcloud docker-compose.yml is located.

Example:

docker-compose exec -u www-data nextcloud php occ versions:cleanup

 
or:

docker-compose exec -u www-data nextcloud php occ trash:cleanup --all-users

 

Posted by Uli Köhler in PHP

mbed STM32 timer interrupt example

You can use the mbed Ticker API to add a timer interrupt to your mbed application. This example will use a Ticker-based timer interrupt to toggle the LED once per second, for example on the STM32F429I-DISCO board:

#include <mbed.h>

DigitalOut led1(LED1);
Ticker ticker;

/**
 * This function will be run once per second
 */
void timerTick() {
  // Toggle LED
  led1 = !led1;
}

int main() {
  ticker.attach(timerTick, 1.0 /* seconds */);

  // What you do in the main loop is not important
  while(1) {
  }
}

 

Posted by Uli Köhler in C/C++, mbed

How to fix Raspberry Pi OpenVPN error “ERROR: Cannot open TUN/TAP dev /dev/net/tun: No such device (errno=19)”

Problem:

You want to setup OpenVPN on your Raspberry Pi but you see an error message like

Fri Jun 26 18:12:35 2020 ERROR: Cannot open TUN/TAP dev /dev/net/tun: No such device (errno=19)
Fri Jun 26 18:12:35 2020 Exiting due to fatal error

Solution:

This error occurs if you’ve installed OpenVPN using sudo apt install -y openvpn but if you didn’t reboot after installing it. In order to fix the issue, reboot using

sudo reboot

 

Posted by Uli Köhler in Linux, Raspberry Pi

How to create filename containing date/time in Python

In datalogging quiten often you have to create a new log file once you start to log data.

Often it’s convenient to include the current date and time in the log file.  In Python, this is pretty easy to do:

from datetime import datetime

filename = f"Temperature log-{datetime.now():%Y-%m-%d %H-%m-%d}.csv"

This will create filenames like

Temperature log 2020-06-17 22-37-41.csv
Temperature log 2019-12-31 00-15-55.csv

Note that if you use another Date/time format, you need to avoid special characters that must not occur in filenames. The rules for which filename is correct are much easier on Linux than on Windows, but since you should be compatible with both operating systems, you should always check the Windows rules.

These characters are forbidden for Windows filenames:

<>:"/\|?*

The date-time format we used above, %Y-%m-%d %H-%m-%d is specially crafted in order to avoid colons in ISO-8601-like date/time formats such as 2020-04-02 11:45:33 since colons would be illegal in Windows filenames (they would work in Linux filenames, though). %Y-%m-%d %H-%m-%d only contains spaces and dash (-) characters in order to avoid any issues with filename rules.

Posted by Uli Köhler in Python

How to fix PlatformIO mbed error: ‘Mutex’ does not name a type

Problem:

You are trying to compile your PlatformIO mbed application using Mutexes like

Mutex myLock;

but you see an error message like

src\main.cpp:3:1: error: 'Mutex' does not name a type
 Mutex myLock;
 ^~~~~

Solution:

Add this line to your platformio.ini:

build_flags = -D PIO_FRAMEWORK_MBED_RTOS_PRESENT

This will enable the RTOS features in mbed, including the Mutex.

Posted by Uli Köhler in mbed, PlatformIO

How to fix PlatformIO fatal error: stm32f429i_discovery_lcd.h: No such file or directory

Problem:

You are trying to compile your PlatformIO application using  the LCD_DISCO_F429ZI library, but you see an error message like

 #include "stm32f429i_discovery_lcd.h"
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
*** [.pio\build\disco_f429zi\src\main.o] Error 1
In file included from .pio\libdeps\disco_f429zi\LCD_DISCO_F429ZI_ID2432\LCD_DISCO_F429ZI.cpp:19:0:
.pio\libdeps\disco_f429zi\LCD_DISCO_F429ZI_ID2432\LCD_DISCO_F429ZI.h:25:10: fatal error: stm32f429i_discovery_lcd.h: No such file or directory

Solution:

First, ensure that BSP_DISCO_F429ZI is listed is library dependency in platformio.ini like this:

[env:disco_f429zi]
platform = ststm32
board = disco_f429zi
framework = mbed
lib_deps =
    LCD_DISCO_F429ZI
    BSP_DISCO_F429ZI

 

Replace the line

#include "stm32f429i_discovery_lcd.h"

in LCD_DISCO_F429ZI.h with

#include "Drivers/BSP/STM32F429I-Discovery/stm32f429i_discovery_lcd.h"

 

Posted by Uli Köhler in C/C++, PlatformIO

How to fix PlatformIO fatal error: ../Fonts/fonts.h: No such file or directory

Problem:

You are trying to compile a PlatformIO application using the BSP_DISCO_F429ZI library, but you see an error message like

In file included from .pio\libdeps\disco_f429zi\BSP_DISCO_F429ZI_ID2208\Drivers\BSP\STM32F429I-Discovery\stm32f429i_discovery_lcd.c:75:0:
.pio\libdeps\disco_f429zi\BSP_DISCO_F429ZI_ID2208\Drivers\BSP\STM32F429I-Discovery\stm32f429i_discovery_lcd.h:49:10: fatal error: ../Fonts/fonts.h: No such file or directory
 #include "../Fonts/fonts.h"
          ^~~~~~~~~~~~~~~~~~
compilation terminated.

Solution:

The BSP_DISCO_F429ZI package includes fonts.h from the wrong directory. Replace

#include "../Fonts/fonts.h"

by

#include "Utilities/Fonts/fonts.h"

in order to fix the issue. You might need to do that multiple times (in multiple files) in order to fix your build.

Posted by Uli Köhler in C/C++, PlatformIO

How to use printf in mbed using STM32F429I-DISC1 and PlatformIO

In PlatformIO, you can directly use printf without any special configuration for the STM32F429-DISC1 discovery board:

#include <mbed.h>

int main() {
  while(1) {
    printf("Hello world\n");
    wait(0.5);
  }
}

This program will print Hello world twice every second. You can watch the output using the PlatformIO Monitor feature.

Posted by Uli Köhler in mbed

How to toggle the STM32F429I-DISCOVERY LED using mbed + PlatformIO

This simple firmare toggles the LED on the STM32F429I-DISC1 discovery board.

#include <mbed.h>

DigitalOut myled(LED1);

int main() {
  while(1) {
    myled = !myled;
    wait(0.5);
  }
}

This will toggle the green (PG13) LED twice per second.

The program is simple: We toggle the LED using myled = !myled; and then use wait(0.5) for 0.5 seconds.

Posted by Uli Köhler in C/C++, mbed

How to create filename containing date/time in C#

In datalogging, often you have to create a new log file once you start to log data.

In most cases, it’s convenient to include the current date and time in the log file. Here’s how you can do that in C# without using external libraries:

string filename = String.Format("Temperature logging {0}.csv",
                                DateTime.UtcNow.ToString("yyyy-MM-dd HH-mm-ss"));

This will create filenames like

Temperature log 2020-06-17 22-37-41.csv
Temperature log 2019-12-31 00-15-55.csv

Note that if you use another Date/time format, you need to avoid special characters that must not occur in filenames. The rules for which filename is correct are much easier on Linux than on Windows, but since you should be compatible with both operating systems, you should always check the Windows rules.

These characters are forbidden for Windows filenames:

<>:"/\|?*

The date-time format we used above, yyyy-MM-dd HH-mm-ss is specially crafted in order to avoid colons in ISO-8601-like date/time formats such as 2020-04-02 11:45:33 since colons would be illegal in Windows filenames. yyyy-MM-dd HH-mm-ss only contains spaces and minus (-) characters in order to avoid any issues, now and in the future.

Posted by Uli Köhler in C#

How to fix C/C++ error: call of overloaded ‘abs(uint32_t)’ is ambiguous

Problem:

You are trying to compile a C/C++ program but you see an error message like

src\main.cpp:127:21: error: call of overloaded 'abs(uint32_t)' is ambiguous

that refers to a line like

long timedelta = abs(millis() - startTime);

Solution:

Cast the argument to abs() to int or another suitable type:

long timedelta = abs(((int)millis() - startTime));

That should fix the error.

The reason for the error message is that millis() and startTime are both unsigned integers (uint32_t), hence their difference (millis() - startTime) is also an uint32_t. However it makes no sense to compute the abs() of an unsigned integer since the absolute value of an absolute-value integer is  always the same as the input argument.

Then, the compiler tries to cast the uint32_t to any type that is compatible with abs(), like int, float, double, … but it doesn’t know which of those types is the correct one to cast it to.

By saying call of overloaded abs() the compiler is trying to tell you that there are multBiple argument types with which you can call abs(), including intfloat, double, … – a function with the same name but different argument types is called overloaded.

By saying is ambiguous, the compiler is telling you that it doesn’t know which of those variants of abs() it should call.

Note that the compiler does not know that all overloaded variants of abs() fundamentally do the same thing, so it won’t just cast your uint32_t into any arbitrary type. Also, there are tiny details in how the abs() variants work – for example, float abs(float) will do a different calculation compared to double abs(double) since it computes with 32-bit floating point numbers (float) as opposed to 64-bit floating point numbers (double).

Hence, the compiler can’t just assume that they are all the same and it doesn’t matter which one it calls, even though they represent the same underlying mathematical operation

Posted by Uli Köhler in C/C++, GCC errors

How to fix C/C++ round(): error: invalid operands of types ‘float’ and ‘int’ to binary ‘operator&’

Problem:

You are trying to compile a C/C++ program but you see an error message like

src\main.cpp:357:21: error: invalid operands of types 'float' and 'int' to binary 'operator&'

that refers to a line like

long m = round(v) & 0x7FF;

Solution:

The result of round() is a floating point number. You are trying to use the & operator to perform bitwise AND of a float and an int (0x7FF in the example above). However, you can not perform bitwise operation on floats in C/C++.

In order to fix this, case the result of round() to int:

long m = ((int)round(v)) & 0x7FF;

That should fix the compiler error.

 

Posted by Uli Köhler in C/C++, GCC errors

What .gitignore to use for LTSpice XVII projects?

Besides the .asc files containing the circuit to simulate, LTSpice XVII genates .log.raw and .op.raw files during simulation. Usually, you don’t want to commit those files.

This is the .gitignore file I use to manage my LTSpice XVII projects:

*.log
*.raw
*.net
*.fft
Posted by Uli Köhler in Electronics

How to fix raspi-config “The splash screen is not installed so cannot be activated”

Problem:

You want to enable the boot splash screen on your Raspberry Pi using raspi-config, but you see this error message:

The splash screen is not installed so cannot be activated

followed by There was an error running option B3 Splash Screen

Solution:

As you can find out from reading the raspi-config source code, it checks for the existence of /usr/share/plymouth/themes/pix/pix.script. In order to install this file, install the rpd-plym-splash package:

sudo apt -y install rpd-plym-splash
Posted by Uli Köhler in Embedded, Linux, Raspberry Pi

How to manually reload Chromium Kiosk

Problem:

You are running a Chromium Kiosk e.g. on a Raspberry Pi using a command like

chromium-browser --noerrdialogs --disable-infobars --disk-cache-dir=/dev/null --disk-cache-size=1 --kiosk http://localhost

e.g. in /etc/xdg/openbox/autostart, but you don’t know how to manuy reload the Kiosk e.g. after you have changed the underlying website

Solution:

In /etc/xdg/openbox/autostart or wherever your chromium-browser command is, enclose it in

while true ; do [CHROMIUM COMMAND] ; sleep 1 ; done

The complete command would look like this, for example:

while true ; do chromium-browser  --noerrdialogs --disable-infobars --disk-cache-dir=/dev/null --disk-cache-size=1 --kiosk http://localhost ; sleep 1 ; done

Now, to manually reload Chromium, all you have to do is to kill the process using

killall /usr/lib/chromium-browser/chromium-browser-v7

This will kill the Chromium process and the while loop will automatically restart it after one second.

In case you see an error message like

/usr/lib/chromium-browser/chromium-browser-v7: No such file or directory

you need to find out which executable is used for Chromium in order to pass that to killall. To find out the name of the executable, use

ps a | grep -i chromium

and look for a string similar to /usr/lib/chromium-browser/chromium-browser-v7.

Posted by Uli Köhler in Embedded, Linux

How to fix Chromium Kiosk still displaying old page after reboot

Problem:

You are running a Chromium Kiosk application on an embedded computer (like a Raspberry Pi) using a command like

chromium-browser --noerrdialogs --disable-infobars --kiosk http://localhost

but when you update the webpage, Chromium still displays the old page even after a reboot.

Solution:

Disable Chromium’s cache by adding

--disk-cache-dir=/dev/null --disk-cache-size=1

to the command (which is typically found in /etc/xdg/openbox/autostart). The full command will look like this:

chromium-browser --noerrdialogs --disable-infobars --disk-cache-dir=/dev/null --disk-cache-size=1 --kiosk http://localhost
Posted by Uli Köhler in Embedded, Linux

What .gitignore to use for KiCAD projects?

KiCAD generates a lot of backup-like files, for example MyPCB.sch-bak that should be ignored by git and don’t need to be committed to the repository.

This is the .gitignore file I use to manage my KiCAD projects:

*-bak
*-backups
*-cache*
*-bak*
_autosave*
\#auto_saved_files\#

Note that TechOverflow’s KiCAD project initialization script automatically generates this.gitignore.

Posted by Uli Köhler in KiCAD
This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Cookie settingsACCEPTPrivacy &amp; Cookies Policy