This is another of those quick posts. Sometimes in Linux/OSX I want (or even need) to rename or copy a file filename to path/filename_date. For instance, let's say the file is called cli64.log. I then can do something like
bash-3.2$ cp cli64.log cli64_`date +%Y%M%d-%H%M.log` bash-3.2$ ls -lh cli64.log* -rw-r--r-- 1 dalek staff 2.8K Feb 21 2013 cli64.log -rw-r--r-- 1 dalek staff 2.8K Mar 23 16:29 cli64_20152923-1629.log bash-3.2$to append the date (as YearMonthDay which in this case turns out to be 20150323) and the time (HourMinute which when I did the above was 1629 or 4:29PM for those who cannot count past 12) to the name. So far so good.
As some of you have guessed -- maybe the title of this article was a dead giveaway -- I sometimes need to deal with Windows. And I do my best to make it behave as close to Linux (using Linux as placeholder for Linux/OSX/whatever since they behave the same in this case. In fact, the machine I ran the above command is a Mac Mini running OSX) as I can, which is why I use Powershell. So, how do I do the same copy command in Powershell?
To get the date, the command we need is Get-Date. When you run it by itself, it gives something like
PS C:\Users\raub> get-date Monday, March 23, 2015 4:41:13 PM PS C:\Users\raub>which is not useful for us; we want to make the date be part of the filename in the format we want. We will work this two part problem starting at the format and then worrying about the concatenation part.
According to the docs, and to http://ss64.com/ps/get-date.html (which has a convenient list of the time formats we can use), we can use the -format option. Let's try and see if we can replicate the output of date +%Y%M%d-%H%M:
PS C:\Users\raub> get-date -format 'yyyyMMdd-HHmm' 20150323-1643 PS C:\Users\raub>That looks very similar to what we did in Linux. How abut adding that to the filename?
So, concatenating strings in Powershell is a bit interesting. Let's say we have $theTestFile=C:\Users\raub\monkey\testfile.txt and we want to append tmp to it. Now we can try a few things and see what we can come up with:
PS C:\Users\raub> echo "$theTestFile" + tmp C:\Users\raub\monkey\testfile.txt + tmp PS C:\Users\raub> echo "$theTestFile" += tmp C:\Users\raub\monkey\testfile.txt += tmp PS C:\Users\raub> echo "$theTestFile += tmp" C:\Users\raub\monkey\testfile.txt += tmp PS C:\Users\raub> echo "$theTestFiletmp" PS C:\Users\raub> echo "$theTestFile tmp" C:\Users\raub\monkey\testfile.txt tmp PS C:\Users\raub> Write-host "$($theTestFile)tmp" C:\Users\raub\monkey\testfile.txttmp PS C:\Users\raub> echo "$($theTestFile)tmp" C:\Users\raub\monkey\testfile.txttmp PS C:\Users\raub>So, the parenthesis thingie seems to be what we want to do.
Putting it all together
Now we know how to get the date and concatenate, if we put the date thingie inside the parenthesis thingie, the equivalent of
cp cli64.log cli64_`date +%Y%M%d-%H%M.log`in powershell is
copy cli64.log "cli64_$(Get-Date -format 'yyyyMMdd-HHmm').log"
Er, we are not done yetBut, you will point out, the title of this article mentions environment variables! Fair enough. So we will expand the original problem. Say, you also want to name the copy of the log file to not only included when it was copied but also the hostname. Reason here is that you or someone else who will get this file might need to know where this file came from. In Linux, that can be done with $HOSTNAME, as in
cp cli64.log cli64_$HOSTNAME-`date +%Y%M%d-%H%M.log`but what about Windows and powershell? Enter the environment variables we talked about. We would hope the computer knows what it is called, amongst other things, right? Let's see what it knows
PS C:\Users\raub> ls env: Name Value ---- ----- ALLUSERSPROFILE C:\ProgramData APPDATA C:\Users\raub\AppData\Roaming CommonProgramFiles C:\Program Files\Common Files CommonProgramFiles(x86) C:\Program Files (x86)\Common Files CommonProgramW6432 C:\Program Files\Common Files COMPUTERNAME VBOX01 ComSpec C:\Windows\system32\cmd.exe FP_NO_HOST_CHECK NO HOMEDRIVE C: HOMEPATH \Users\raub LOCALAPPDATA C:\Users\raub\AppData\Local LOGONSERVER \\ZOOL NUMBER_OF_PROCESSORS 1 OS Windows_NT Path %SystemRoot%\system32\WindowsPowerShell\v1.0\;C:\ProgramData\Oracle\Java\javapath;C:\... PATHEXT .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC PROCESSOR_ARCHITECTURE AMD64 PROCESSOR_IDENTIFIER Intel64 Family 6 Model 60 Stepping 3, GenuineIntel PROCESSOR_LEVEL 6 PROCESSOR_REVISION 3c03 ProgramData C:\ProgramData ProgramFiles C:\Program Files ProgramFiles(x86) C:\Program Files (x86) ProgramW6432 C:\Program Files PSModulePath C:\Users\raub\Documents\WindowsPowerShell\Modules;C:\Windows\system32\WindowsPowe... PUBLIC C:\Users\Public SESSIONNAME Console SystemDrive C: SystemRoot C:\Windows TEMP C:\Users\raub\AppData\Local\Temp TMP C:\Users\raub\AppData\Local\Temp UATDATA C:\Windows\CCM\UATData\D9FFC898-CBB8-491d-D8CA-173A9FF1B077 USERDNSDOMAIN EXAMPLE.COM USERDOMAIN EXAMPLE USERNAME raub USERPROFILE C:\Users\raub windir C:\Windows PS C:\Users\raub>That looks very impressive. How do we get that info in a way we can use when renaming out file? Here is how you get the hostname:
PS C:\Users\raub>$env:computername VBOX01 PS C:\Users\raub>
So, if we wanted to copy poor cli4.log to some directory in some drive, adding to the new filename the hostname and date the file was copied, we could do a lot worse than
copy cli64.log "J:\kitchen\fridge\cli64_$env:computername-$(Get-Date -format 'yyyyMMdd-HHmm').log"
So I think we might have made managing Windows be a bit saner than before.