Episode 5 File management part 1

We use mv to move and rename files, and create a shell alias to improve the safety of one of its sharp edges. We also introduce the .bashrc configuration script, and mkdir to create directories.

25 August 2015

[Rhythmic, dark electronic intro music]

League

Welcome back to Command Line TV. Last time we talked about text manipulation using

commands like cut, sort, and uniq. And what are we doing today?

Lopes

Today we’ll be doing more file management. We’ll be using the move (mv) command,

the copy (cp) command, remove (rm) and then we’ll touch base on removing and making directories.

League

Great. So the mv and cp commands I think is where we’ll start. And there

are two ways to use these commands. I’m going to get the usage screen – the help

screen for the mv command. So thats the -- help and we’ll pipe that into

mv --help | less

less And the two ways are summarized by these top two lines here, the third

one is just an alternative to another of them. But the first way that you use

mv is you specify a single source and a single destination. These are file

names and so what it means is that you are moving – actually, you’re renaming the

file to a different file name. So this version of the command could just be

called ‘rename’, and on other systems it might be called rename. So let’s take a

look at trying that version of the mv command first. So I’m in my Downloads

folder and I’ve got a couple of files here. Let’s say that I want to take this

weblog.txt and rename it maybe to put a date in the file name or something

like that. So I can do mv weblog.txt and then I just give a destination name

which could be like weblog-2015-07-11.txt something like that. And so my move

mv weblog.txt weblog-2015-07-11.txt

command had a source and a destination. when I do ls now, the name of that file

has changed but it’s exactly the same content. Now the destination doesn’t

have to be in the same directory. You can specify a different directory where

it will go. So then it feels like a little bit more than a rename. So let’s

say for example, if I want to move my languages file into the thinkjava

directory, but I might also rename it at the same time. so I could call it

“internationalization” or something like that .txt. So, this is a rename

mv languages.txt thinkjava/internationalization.txt

combined with also moving it into a subdirectory. And that works fine.

So if I ls from up here, that languages.txt is gone, but if we look inside the

thinkjava which I can do with cd there first and ls or I can just say ls

ls thinkjava

and the name of that directory. You see here that internationalization

file is now in that directory.

The second way to use mv is – let’s get back this less command – is you move

multiple source files. So the dots here mean I can specify multiple sources – you

might want to use a wildcard to specify multiple sources. And then the last thing

you specify is a destination directory. It’ll keep the names of all those files

but then move them all into that destination directory. So let’s say for

example – I’m going to go down into my thinkjava/figs folder. We’ve been here

before to look at images and so forth. And there are different formats here.

So eps and fig as well as different prefixes. And I could move them into

separate folders. So for example let’s make a separate folder for fig and

for eps. so I’m going to also introduce this command – this is one of the

simplest commands there is – called mkdir spelled “m k d i r” – that creates

mkdir fig eps

a new directory and we can specify just one directory name or multiple directory

names and those would get created if they dont exist yet. So now I’ve got listed

here among all my other files I’ve got an eps and a fig folder. And now I’m

going to use mv – the second version – along with a wildcard so I say *.fig

mv *.fig fig

and the destination directory is called fig. Or mv *.eps and the destination

mv *.eps eps

is eps. And now this looks a lot cleaner because all of those files are

in their various subfolders.

Lopes

Now professor, when I originally learned about the mv command I know it was

especially dangerous to use it if files already existed and you might

overwrite something.

League

Yeah, it’s a real sharp edge of the way mv works is that when that destination

already exists – if you’re using the first form where you’re just renaming –

if that destination file exists, it will just overwrite it and it doesn’t

even tell you that it did that. So let’s go back up here to my regular

downloads folder where I created this weblog.txt. So let’s say that I want

to rename survey – let’s imagine that this survey actually is a weblog – so

mv survey.tsv weblog-2015-07-12.txt

I want to rename it and give it a different date, right. So I put 12 or

something like that. Now that will be harmless because that file doesn’t

exist. But what if I make a typo or something and I put a file that does

exist? This will rename survey.tsv into that weblog for July 11th. And it

mv survey.tsv weblog-2015-07-11.txt

overwrote the old one. If I do ls there’s no more survey.tsv. However

this file contains the content from the old survey.tsv and the old content

from this weblog file is gone, it just doesn’t exist anymore. So if I do

head on this we’ll see that it’s actually the survey data and not the

head weblog-2015-07-11.txt

weblog data. So yeah, that’s a really dangerous thing to do. It’s especially

dangerous if you’re using wildcards. So sometimes you will mean to use a

wildcard in order to move multiple files into a destination directory, right. So

let’s say I mkdir hello and I want to move hello-2.10.tar* so basically this

mkdir hello

use of a wildcard here will match both of these files right, the tar.gz as

well as the `tar.gz.sig’. So I want to move both of those files into the

destination directory hello alright. That will work fine. However, what if I

mv hello-2.10.tar* hello

just forget to put the destination directory? Now what happens is this

wildcard happens to expand to two separate files, right? So that expansion is what’s

going to happen first. It’s going to become the tar.gz as well as the

tar.gz.sig and now my command looks like that. I don’t have to type this,

this is just what the wildcard expansion will do. And so now instead of triggering

the second form where we’re moving to a directory, it’s triggering the first

form where i’m just renaming. And remember that that rename can clobber

something so now I’m just missing one of those files, it’s gone. So that’s a

real sharp edge. There are a couple of things that you can do to make that a

little bit more safe – a little easier to deal with. One thing that you can do

is, there are a couple of options to do – like there’s something called mv -n.

Let’s take a look at the help page again. ‘-n’ stands for “no clobber” so do not

mv --help | less

overwrite an existing file. So if I had remembered to specify -n before I did

that – let’s actually put back – I’m just going to fake this by creating an empty

filename. So if I just create an empty .gz file using my editor and save it

nano hello-2.10.tar.gz

– we covered nano previously. Now I’ve got, not the original content, but at

least I’ve got two files with that name so I can try it again. So if I do

mv -n hello-2.10* it didn’t give me an error message but it didn’t do the move.

mv -n hello-2.10.tar.gz*

It left both the files alone. Another way besides -n is -i which is for

interactive. So we’ll try that as well. What interactive does is it prompts you

mv -i hello-2.10.tar.gz*

whether you really want to overwrite files or not. And you can type yes or no.

So I say “oh I didnt mean to overwrite that file” so I’ll do n.

So those are two options to mv that make it a little bit safer.

Another technique is inherent in that third format of mv. So this does the same

thing as the second format, it moves a bunch of source files into a target or

destination directory, but by specifying the directory first, maybe you’re less

likely to forget to put it, right. So if I wanted to move both of these

hello files into the hello directory, I might say mv -t hello – I’m

mv -t hello hello-2.10.tar.gz*

moving stuff into there, and then do hello-2.10.tar.gz*. And now both of

those are gone from this directory but they’re both present in the sub-directory.

So those are a couple of options for the move command.

Lopes

It seems like the move command should automatically have the -n or the -i

League

embedded into it for safety reasons. Is there anything we can do about that?

Yeah, the philosophy of Unix is often that you know what you’re doing and if

you don’t, if you’re making a mistake, then it doesn’t do a lot to prevent it.

Unix commands in general are not meant to protect you from yourself, and in

fact one time when I was a teaching assistant, we had two different

sections of a programming course that we were teaching and we kept the grades

in two seperate spreadsheet files. And I wanted to move both of them into, or

maybe copy both of them – I don’t remember – into a different directory.

So I did like cp *.spreadsheet whatever, and that ended up taking one

of those files and using that data to overwrite the other file, so we lost

the grades for one of our sections. We did have a backup of them but you

know, we lost a couple days of work. So the other TA’s were not very happy

with me. But there is a way if you would like to have greater defenses

for this kind of thing, to ensure that. So we can make it so that the -n or

-i commands are automatic. The way to do that is what we call an alias.

So the way an alias works is you type alias and then the name of the command

you want to create. So for example we can make a brand new command. lt is

not a command that exists on Unix system generally. But I can make a command

called lt by declaring an alias. Then I just specify an equal sign and

alias lt='ls -ltr'

quotes, usually single quotes but probably could be double quotes. And I

want that to stand for this ls -ltr which I said I use all the time right,

because it shows me detailed listing in reverse chronological order.

So I declare that alias and now when I type lt it does that ls -ltr and

lt

the most recent stuff is at the bottom. So I can do that same thing for the

mv command, and let’s say I want to use mv -i by default. So -i is the

alias mv='mv -i'

interactive one. And now that I’ve got that alias set up, if I go down into

hello where I’ve got these two files and I try to do mv hello* the way

mv hello*

that would have worked by default is it takes one of those and overwrites

the other one. But because of my alias with -i it will ask me to overwrite,

and so I can just say no. Now we would like to save that for

the future as well. An alias, if I just type it at the command line like that

will only be good for the current session and when I close this terminal

or log out, it’s gone. So I’d like to keep it longer than that. To do that

I’m going to go up to my home folder which is ~ and we’re going to look

cd ~

at what we call the ‘dot’ files. So ls hides some files from us by

ls -a

default. Any file name or directory that starts with a . is meant to be

hidden out of the way, but the -a on ls will show them. So one of those

files here – well two of them – are .bash_profile and .bashrc. And if

bash is your shell which it probably is then profile is a file where you can

put definitions and configurations that will get read every time you

log in and then .bashrc gets read every time you start a new terminal

or new shell. So you can probably put it in either one. Let’s go with the

.bashrc. So im going to run my nano editor on .bashrc. If you don’t

nano .bashrc

already have your .bashrc or bash_profile this command will still

work fine, you’ll just create a brand new file. Mine will show that that file

already exists because when I created a new user on this system it gave me a

default .bashrc. But if this is empty to start out it’s no problem. You can

see here it’s already got an alias for ls this explains why we had the color

output on ls. It was giving a --color option to ls whenever we type it

because of that alias. So I’m going to go just below that somewhere and do my

mv alias to mv -i and let’s also do it for cp – we havent really talked

alias mv='mv -i'

about copy – but its got the same sort of issues. So I create those aliases

alias cp='cp -i'

and I’m going to save that with control-O and exit with control-X.

And now to get that to take effect in the current shell without restarting

the terminal I can type source .bashrc. So now that cp alias should be available.

source .bashrc

If I go down to hello again – I guess it’s Downloads/hello/ – and we’re going

cd downloads/hello

to do the cp on these files. So this means copy one file to a different

cp hello-2.10.tar.gz*

filename. It won’t remove the original which maybe is an improvement.

But cp by default will clobber the destination if it already exists. But

since I added that alias for -i its asking whether to overwrite. so I’ve

been able to use aliases to make those commands a little bit safer.

Today we learned to use mv to move and rename files, and some basics of cp to

copy files. We also learned how to make a simple alias and to edit our .bashrc to

customize settings beyond the current terminal. We’ll continue with more file

management next time. Thanks for joining us.

[Dark electronic beat]

[Captions by Christian Lopes]

[End]