• How to schedule a task for rclone in windows

    I recently wrote a blog post about how I made a backup of my google drive with rclone. Whenever I want to make a backup however I still have to do it manually by entering the rclone command in my terminal. Because I want the backups to happen regularly without me having to think about it I decided to automate it. This blog post will be about how I scheduled a task in windows to back up my google drive using rclone every hour my computer is on.

    This was my first time using the windows task scheduler but luckily there are enough resources online which explain how to use it. It’s pretty straightforward and you can look at existing tasks to get an idea how they work and what the best settings are. The most important tabs are general, triggers and actions the rest you can just leave as is.

    The first thing you want to do is create a new task by clicking “create task”, don’t click on “create basic task” because it won’t give you all the options you need. After that give your task a name and optionally a description. I changed “configure for” to windows 10 but I don’t think it really matters. Now you can switch to the triggers tab and create a new trigger. I configured mine to run every day and repeat every hour for the duration of a day but you can also run it only one time and let it repeat indefinitely although I’m not sure how that will work out. With that done we can switch to the actions tab which is arguably the most important one since we define which program we’ll want to run and with what parameters. Create a new action and under program/script browse to the rclone executable. Next add the arguments you want the program to receive when it’s executed. In my case this is:

    sync googledrive: stack:googledrive
    

    because I want my google drive to be synced to the googledrive directory in my stack. After that you can exit out of both windows by clicking OK.

    To see if our task actually works we should give it a test run. Select the task from the list and click run in the right column. This should open a console window and run whatever program you selected, in my case rclone. After it’s done it should close again and if you refresh the list you should see when the task last ran and what the exit code was in the “last run result” column. If everything went well you can leave your task as is otherwise you should edit your task till you get the desired result. It took me a few iterations until I had configured everything correctly.

    As you’ve probably noticed every time it runs your task it will open a terminal. While this may be desirable when you’re testing if everything works it’s not very nice if it pops up every time while you’re doing something else. The best and easiest solution I’ve found for this so far is to go to the general tab of your task and selecting the option “run whether user is logged on or not” and ticking the “do not store password” box. This somehow hides the program you’re running but I’m not quite sure how. If you want to make sure your task is still running your program after making this change you can open the task manager and look for the program after you started the task. If everything is working correctly it should still show up.

    You should be all set now. I’ve been running this task for 4 days now and haven’t had any issues yet. All my files are being synced and show up in my other cloud storage.

  • Backing up my google drive with rclone

    It’s common knowledge that you should always try to back up your files in more than one place. For the longest time I’ve been backing up my files to only my google drive and while I think google drive is very reliable it did make me feel a little uneasy that my files were only stored in one place.

    That is why yesterday I decided to start backing up my google drive to another cloud storage provider. There are a lot of tools out there that can do the job for you but they’re often paid or have some kind of limit to how many files you can transfer. That’s why I was happy to find a tool that was open source and could be used with a lot of different cloud providers.

    Rclone is very well documented and I think anyone that’s able to use the command line should be able to figure it out. If you want to try it out for yourself you can head over to https://rclone.org/ and follow their very comprehensive documentation. If you’d like to know how I did it please keep reading. I did this on a windows machine but it should work just as well on any other platform.

    First thing I did was download the rclone binary from the website and add it to my environment variables. This allowed me to access the program from powershell. You can simply type:

    rclone
    

    And you’ll get a list of available options.

    The first thing you want to do is configure the services you’re going to use. You can do this by typing:

    rclone config
    

    Which will give you an interactive menu which leads you through the process of adding and removing services. To create a new service you simply type n and hit enter. You’ll give the services a name and choose which cloud storage provider you want to use. In my case google drive. After that you’ll get a prompt telling you that it’s recommended to configure your own google application client id. You can skip this step if you want and just accept the default but since I didn’t want to run into any limitations I opted to configure my own client id and secret so I wouldn’t run into any limitations. After that you can hit enter through the rest of the process and accept all the defaults.

    Now that we’ve got google drive configured we can configure the other cloud storage provider which is pretty much the same process only this time I called the service stack and chose webdav as the storage type since this is what stack is using.

    With both services configured we can start transferring files from one storage provider to the other. Because I want to move my files from google drive to stack I used the following command:

    rclone sync googledrive: stack:googledrive -P
    

    What this does is sync the root of my google drive to a folder called googledrive in my stack. The -P flag is used to show the current progress because it doesn’t show any progress by default. If you don’t specify a path it will transfer the files to the root of that service which is something you probably don’t want so make sure to specify a path where you want the files to be placed.

    This made it really easy for me to transfer all my files from my google drive to my stack and it should also be really easy for me to automate in the future.

  • The righ way to develop using WSL2

    I recently tried to set up a react app using WSL2 but I couldn’t get it to work. The dependencies took really long to install or failed to install at all. I previously set up a react app using WSL1 without any problems so I was wondering why it wouldn’t work under WSL2. When I finally did manage to install the required dependencies and got it to load in the browser it didn’t automatically update the app after I made a change to the code.

    At this point I was so frustrated with the development experience that I installed Fedora next to Windows and developed the app there without any problems. I must say that developing on Fedora is a really nice experience were it not for the few things that really grind my gears. For example it’s not possible to set the scroll speed of your mouse and the US International keyboard just doesn’t work like I’m used to. For this reason I’m still using Windows as my main operating system and that’s also why it would be really nice to get WSL2 to work properly.

    Anyway today, a few weeks later, I decided to give it another go. I read somewhere that WSL2 now uses its own hard drive and that you shouldn’t work on the mounted Windows drive like I used to do with WSL1. This wouldn’t be the first thing you’d think of doing because whenever you start WSL2 you get dropped in the mounted Windows drive and not your home directory.

    With all this in mind the first thing I did was change my directory to the real home directory after I logged in. After that I did what I usually do when creating a react app and lo and behold it worked like a charm on the first try! On top of that the dependencies installed way faster and whenever I made a change to my code it would recompile faster than ever before.

    I’m glad I found out what the issue was and I’m looking forward to developing more projects using WSL2. The integration with Docker and Visual Studio Code is great and makes for a really nice developer experience.

  • An efficient way to bake pancakes

    I can’t help but try to do things as efficiently as possible. I’m not quite sure why but I guess to keep myself from being bored I try to change the way I bake pancakes every now and then. The changes I make are not big and I think most people wouldn’t even notice them. That being said I think that through the years I’ve found a pretty efficient way to bake pancakes.

    First I’ll show you the recipe and after that I’ll describe how I make the process efficient.

    Ingredients:

    • 2 eggs
    • 250 grams of flour
    • 500 ml of milk
    • pinch of salt (optional)
    • Sunflower oil

    Cookware:

    • Bowl
    • Wisk
    • Pan
    • Scale
    • Ladle

    Preparation:

    1. Put 2 eggs into a bowl and add a pinch of salt if you like.
    2. Wisk the eggs
    3. Add 250 grams of flour
    4. Add 200 ml of milk
    5. Wisk till you’ve got a smooth batter
    6. Add 300 ml of milk
    7. Wisk till the rest of the milk is dissolved into the batter
    8. Heat a pan on the stove
    9. Put a drop of sunflower oil in the pan
    10. Turn the pan to spread the oil
    11. Use the ladle to pour the batter into the pan
    12. Rotate the pan slowly while you pour the batter
    13. Let the pancake sit till the top is dry
    14. Flip the pancake
    15. Put the pancake on a plate

    The best way to wisk I’ve found is by making a quick motion from right to left and only occasionally making a circle.

    I think the biggest time saver is to use one of those scales where you can put the bowl right on top and then reset it to 0. After you’ve wisked the eggs you can just leave the wisk in the bowl and put it on the scale. After that you reset the weight back to 0 and add your 250 grams of flour and the repeat same steps to add your 200 ml (about the same as 200 grams) of milk. When you’ve added all the ingredients you can wisk everything into a nice smooth batter and add the last 300 ml of milk.

    I used to measure the flour and milk separately which caused me to have more dishes than necessary and it took more time because I had to put the milk and flour into separate containers.

    You might ask yourself why I wouldn’t just add the 500 ml of milk in one go, after all this would reduce the amount of steps required. The reason I don’t do this is because this will cause the batter to have lumps in it which are really hard to get rid off assuming this is even possible.

    I hope you enjoyed my thoughts on pancakes and have found some useful tips to make the way you cook your pancakes more efficient.

  • How to find the missing numbers in an array

    If you just want to know the solution please jump to the end of the post where I post the full solution.

    Let me give you a bit of a background story as to how I encountered this particular problem. Although I don’t think it’s all that uncommon so I’m sure there’s lots of other ways to encounter it.

    I like to listen to this radio show called A state of trance it’s hosted by Armin van Buuren and they play mostly trance music. I don’t really like to listen to the most recent episodes because there’s way too much talking but I do like to listen to the old episodes which contain mostly music. This is the reason I went to archived episodes to pick an old episode to listen to.

    To my surprise there were only 498 files listed even though the first file was called filename_000 and the last file was called filename_499. Something which would make you expect 500 files instead of 498. I tried to find the missing episodes but I soon gave up because I knew this would be a tedious task.

    With this problem in the back of my head I started looking at the rest of the page and I soon found a M3U file. A M3U file is basically a console file with on each line the location to a media file. In my case all the locations to every state of trance episode in the archive. It looks like this:

    http://archive.org/download/Armin_van_Buuren_A_State_of_Trance_001-499/Armin_van_Buuren_A_State_of_Trance_Episode_000.mp3
    http://archive.org/download/Armin_van_Buuren_A_State_of_Trance_001-499/Armin_van_Buuren_A_State_of_Trance_Episode_001.mp3
    http://archive.org/download/Armin_van_Buuren_A_State_of_Trance_001-499/Armin_van_Buuren_A_State_of_Trance_Episode_002.mp3
    ...
    

    The first thing I had to do was extract all the numbers from this file. Something which should be fairly trivial but as you will see later I still ran into some problems. I went to regexr.com, pasted in the contents of the file and came up with the following pattern:

    /(\d+)\.mp3/g
    

    Capture every digit followed by .mp3.

    regexr.com has a handy list feature which allowed me to create a comma separated list of numbers by writing the following pattern:

    $1, 
    

    Output the first capture group followed by a comma.

    After which we end up with:

    000, 001, 002, ...
    

    Try it yourself

    Alright with that out of the way we can finally start writing some code to figure out which numbers are missing. I started with something like this:

    const numbers = [000, 001, 002, 003, 004, 005, 006, 007, 008, 009, 010, 011, 012, 013, 015, 016, 017, 019];
    
    for (let numberIndex = 0; numberIndex < numbers.length; numberIndex++) {
        const number = numbers[numberIndex];
    
        if (number !== numberIndex) {
            console.log(numberIndex);
            break;
        }
    }
    

    For this example I’ve used a smaller array of numbers and used different missing numbers.

    Now if you are coding in a good editor you’ll probably already notice something is off but I was coding on codepen.io and the warning wasn’t that clear. You should note that the missing numbers here are 14 and 18 and that’s what I expected as my output. But what I got instead was:

    10
    

    This took me by surprise so I decided to also log the number to the console to find out why they were not equal. Now my code looks like this:

    const numbers = [000, 001, 002, 003, 004, 005, 006, 007, 008, 009, 010, 011, 012, 013, 015, 016, 017, 019];
    
    for (let numberIndex = 0; numberIndex < numbers.length; numberIndex++) {
        const number = numbers[numberIndex];
    
        if (number !== numberIndex) {
            console.log(number);
            console.log(numberIndex);
            break;
        }
    }
    

    After which the console outputs:

    8
    10
    

    I’m asking myself why 010 equals 8 and know something fishy is up with the notation of my numbers. I google javascript 010 equals 8 and find out that by adding a 0 in front, the number is parsed as base 8 (octal). I’ve got 2 options now. I can turn all the numbers into strings and parse them as decimals or I can remove the leading 0’s. I pick the latter.

    I return to my regex pattern and after some struggles this is what I come up with:

    /(0|[1-9]\d*)\.mp3/g
    

    A 0 or a digit between 1 and 9 followed by any number of digits and .mp3.

    This removed all the leading 0’s and turned my numbers into this:

    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 19, 
    

    Try it yourself

    Okay let’s try the following code:

    const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 19];
    
    for (let numberIndex = 0; numberIndex < numbers.length; numberIndex++) {
        const number = numbers[numberIndex];
    
        if (number !== numberIndex) {
            console.log(numberIndex);
            break;
        }
    }
    

    Success! It outputs:

    14
    

    I open the M3U file in my editor and jump to line 14 (or the equivalent line in my file) and low and behold it shows the number 015. But I think to myself I’ve only found the first number how do I find the second number. This is a piece of cake! Just add 1 to the numberIndex for every number you’re missing.

    const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 19];
    let addition = 0;
    
    for (let numberIndex = 0; numberIndex < numbers.length; numberIndex++) {
        const number = numbers[numberIndex];
    
        if (number !== (numberIndex + addition)) {
            console.log(numberIndex + addition);
            addition++;
        }
    }
    

    Output:

    14
    18
    

    Alright nice that’s exactly what I wanted. I’ve now found the 2 missing episode numbers. I guess I could stop here and everything would be right in the world.

    But something was telling me that I couldn’t stop there because what if there was more than 1 missing number in a row or if the order was wrong? Let’s play the devil and see how my code performs.

    const numbers = [0, 1, 2, 3, 20, 8, 9, 10, 11, 12, 13, 17, 18, 19];
    let addition = 0;
    
    for (let numberIndex = 0; numberIndex < numbers.length; numberIndex++) {
        const number = numbers[numberIndex];
    
        if (number !== (numberIndex + addition)) {
            console.log(numberIndex);
            addition++;
        }
    }
    

    Output:

    4
    5
    6
    11
    12
    13
    

    It kind of works but it soon starts falling apart.

    The sorting part is trivial just call the sort method on the array like so:

    numbers.sort((a, b) => a - b);
    

    Which turns the array into:

    [0, 1, 2, 3, 8, 9, 10, 11, 12, 13, 17, 18, 19, 20]
    

    Don’t try to call it without your own comparison function because that will sort the numbers alphabetically and turn your array into this:

    [0, 1, 10, 11, 12, 13, 17, 18, 19, 2, 20, 3, 8, 9]
    

    Something you probably don’t want.

    Okay let’s focus our attention on finding the missing numbers again. This is what our code looks like now:

    const numbers = [0, 1, 2, 3, 20, 8, 9, 10, 11, 12, 13, 17, 18, 19];
    let addition = 0;
    
    numbers.sort((a, b) => a - b);
    
    for (let numberIndex = 0; numberIndex < numbers.length; numberIndex++) {
        const number = numbers[numberIndex];
    
        if (number !== (numberIndex + addition)) {
            console.log(numberIndex);
            addition++;
        }
    }
    

    My first thought was to figure out the next number in the array and adding the difference between the next number and my current number to the addition but this seemed to be getting messy. I already wasn’t very happy by adding an addition to my numberIndex before comparing it and I would also have to check if we were already at the end of the array.

    I realized I didn’t really have to check the first number because it doesn’t have any numbers before it. I also realized that I could compare the previous number to the current number to figure out if a number was missing by subtracting them from each other. After all if the number was bigger than 1 that would mean we had a missing number. And last but not least it would avoid me from using the index to perform checks, something which was nagging me too.

    A few alterations later my code looked like the following:

    const numbers = [0, 1, 2, 3, 20, 8, 9, 10, 11, 12, 13, 17, 18, 19];
    let addition = 0;
    
    numbers.sort((a, b) => a - b);
    
    for (let numberIndex = 1; numberIndex < numbers.length; numberIndex++) {
        let currentNumber = numbers[numberIndex];
        let previousNumber = numbers[numberIndex - 1];
        let difference = currentNumber - previousNumber;
    
        if (difference !== 1) {
            for (let addition = 1; addition < difference; addition++) {
                console.log(previousNumber + addition);
            }
        }
    }
    

    Output:

    4
    5
    6
    7
    14
    15
    16
    

    Finally I can sleep in peace!

    Original code pen for my answer.

    What if you would have to find the missing numbers in base 8 (octal)?