You can use strace for this:
strace -f -e trace=file command args...
strace traces system calls and prints a description of them to standard error as they occur. The -f option tells it to track child processes and threads as well. -e lets you modify the calls it will track: -e trace=file will log every use of open, unlink, etc, but no non-file actions.
If you want to see what was read from and written to files, change it to -e trace=file,read,write instead; you can list out any additional calls you want to examine there as well. If you leave off that argument entirely you get every system call.
The output is like this (I ran mkdir /tmp/test in a traced shell):
[pid 1444] execve("/usr/bin/mkdir", ["mkdir", "/tmp/test4"], [/* 33 vars */]) = 0
[pid 1444] access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
[pid 1444] open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
[pid 1444] open("/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
[pid 1444] open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
[pid 1444] mkdir("/tmp/test", 0777) = 0
[pid 1444] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1444, si_status=0, si_utime=0, si_stime=0} ---
You can log to a file instead of the terminal with -o filename, and make the output (even) more verbose with -v. It's also possible to attach to an already-existing process with -p PID, in case that's more useful.
If you're looking to do this programmatically, rather than to inspect yourself, look at the ptrace call, which is what strace is built on.
fatrace