3

I'm editing a project in GEdit (text editor). When I type TODO it highlights it yellow for future reference. I have quite a few of these TODOs around the place.

To make it clearer what I need to do, can anyone show me a way to extract any TODO lines from a bunch of files and put them into one text file called, for example, TODOs.txt?

I have something like this:

// TODO: Error handling.

And want it to be put in a file like this:

* <file name> <line number> Error handling

A Linux application (CLI, GUI don't mind) would be preferable, but a regex script or another method someone could come up with would be cool.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Bojangles
  • 99,427
  • 50
  • 170
  • 208

7 Answers7

2

try grep TODO -rnf * > TODOs.txt

Riley Lark
  • 20,660
  • 15
  • 80
  • 128
  • I used `grep TODO -n * > TODOs.txt`. Thanks very much! I never knew it was that simple. Would you know of a way to remove any tabs or spaces preceding the `//` characters at the beginning of the TODO line? – Bojangles Nov 24 '10 at 21:31
  • In reply to the first comment, you could use `grep 'TODO.*' -rno * > TODOs.txt` to not include output from before it. – EdoDodo Nov 25 '10 at 11:07
2

If the file is git version controlled, you might want to reuse git's grep. To grep for TODOs in your source files you type the following command at the root of the repo

git grep TODO

The command outputs something like this:

[~/projects/atl][ros] > git grep TODO
atl_gazebo/src/plugins/quadrotor_gplugin.cpp:  // TODO: switch to attitude controller when in offboard mode

To include the line number add the -n flag:

[~/projects/atl][ros] > git grep -n TODO
atl_gazebo/src/plugins/quadrotor_gplugin.cpp:92:  // TODO: switch to attitude controller when in offboard mode

For more options docs are here.

chutsu
  • 13,612
  • 19
  • 65
  • 86
1

Riley Lark's (and EdoDodo's) answers are probably the most concise, however to not have the literal "TODO" text to show up in the output, you could use ack:

ack --no-group 'TODO (.*)' --output=' $1' > TODOs.txt

Output:

lib/Example.pm:102: Move _cmd out into a separate role
lib/Example.pm:364: Add a filename parameter
lib/Example2.pm:45: Move comment block to POD format

If you wanted some slightly different formatting then adding the --no-group option would provide:

lib/Example.pm
102: Move Move _cmd out into a separate role
364: Add a filename parameter

lib/Example2.pm
45: Move comment block to POD format
pragmatic
  • 11
  • 2
1

If your list of files which has TODO in them is stored in a file, say named "file_list.txt", run:

grep -n `cat file_list.txt` > TODOs.txt

This will retrieve a list of all the lines containing "TODO" string, prepended with filename and line #, and store that in TODOs.txt

DVK
  • 126,886
  • 32
  • 213
  • 327
  • BTW, if you want the exact format "* Error handling", that can easily be done as well but I assumed that the format was not important – DVK Nov 24 '10 at 21:28
  • nah the format given by `grep` is fine :-) I just needed the rough information. – Bojangles Nov 24 '10 at 21:34
0

This will recursively find any line with '// TODO' in any file under the current directory:

grep -rn '// *TODO' .

This cleans up the output a bit:

grep -rn '// *TODO' . | while read l; do
        echo "$(cut -d : -f 1,2 <<<"$l"):$(sed 's|.*//[[:space:]]*TODO||' <<<"$l")"
done

Note that this might break if there are colons (:) in your source code file names.

You can put the output in a file with a final redirection.

EDIT:

This is even better:

grep -rn '// *TODO' . | sed 's|^\([^:]*:[^:]*:\).*//[[:space:]]*TODO|\1|'
thkala
  • 84,049
  • 23
  • 157
  • 201
0

Here's a command that will find all the TODOs in the directory you're in, and it's subdirectories, and put them in a text file:

grep 'TODO' -rn * > TODOs.txt

EDIT:

To remove the unnecessary output before it, you could use this command instead:

grep 'TODO.*' -rno * > TODOs.txt
EdoDodo
  • 8,220
  • 3
  • 24
  • 30
0

Hade the same issue so came up with a simple python script to do it using git grep...

import os
import subprocess
from contextlib import suppress

result = subprocess.run("git grep -l TODO", stdout=subprocess.PIPE)
lst = result.stdout.decode().split("\n")

with suppress(Exception): lst.remove(os.path.basename(__file__)) # remove this filename
with suppress(Exception): lst.remove("") # remove empty filename

todos = []
for file in lst:
    with open(file) as reader:
        for idx, row in enumerate(reader):
            if "TODO" in row: todos.append((file, idx, row))

for todo in todos:
    print(todo)
Scurrae
  • 31
  • 4