Skip to main content

Using Find and Executing a Command

·361 words·2 mins

I mostly work on django projects and as a dev who likes shortcuts, I wanted to have an alias of pm for python manage.py.

I could’ve just added

alias pm="python manage.py"

inside of my config but I was working on different projects where manage.py was located in different folders. Typical projects have it located under root while some projects have it under src/manage.py.

What I needed was a way to find where the manage.py was located and use that so I can do

$ pm runserver # OR
$ pm shell # OR
$ pm <command>

Here’s my first attempt:

$ find . -type f -name "manage.py" -exec python {} \; -quit

What this does is find under the current directory . a type of file -type f with a name of manage.py -name "manage.py". And then, for the file you found execute a command -exec The {} is the current file name returned by find command.

In our case it’s gonna be:

$ python ./src/manage.py

The -quit is optional in most cases of using the find exec command since it it exits immediately after the first match.

But there’s a problem with that approach. If we just do:

$ alias pm="find . -type f -name "manage.py" -exec python {} \; -quit"
$ pm runserver

We get:

$ find: runserver: unknown primary or operator

In order to fix that, we have to wrap it inside a function so that it could take arguments:

$ alias pm='f(){ find . -type f -name "manage.py" -exec python {} "$@" \; -quit; unset -f f; }; f'

The $@ stands for all other arguments you passed. You can add that inside of your .bashrc or .zshrc.

If you are using fish like me, I have this file inside my ~/.config/fish/functions/pm.fish

function pm --description "Find and execute manage.py"
    command find . -type f -name "manage.py" -exec python {} $argv \; -quit
end

Now it works fine!

$ pm runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (2 silenced).
November 16, 2020 - 06:16:50
Django version 2.2.17, using settings 'myproject.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.