
On 8/10/19 12:08 am, Andrew Greig via luv-main wrote:
On 7/10/19 8:37 pm, Andrew McGlashan via luv-main wrote:
for x in 6H9*;do mv -v "${x}" "${x/H/J}";done
Hi Andrew, That is a very elegant one liner. So this one just changed the H to a J
Let's see if some light is entering the brain at this late hour So this - for x in 6H9* - is saying for the input 6H9* (all files in the directory with 6H9as a prefix) then do the exchange of the J for the H using the move command mv which is another way to rename; -v for verbose will print the outcome on screen and after that it looks like the swap but I am lost from this point. But grateful.
I've been "reprimanded" in the past for doing something like for filex in $(ls 6H9*) ... Everyone says, don't use "ls", it isn't needed. And yes, "for filex in 6H9*" ... or any variable name in place of filex for that matter works just fine to collect all files that match in the current directory. If you need directory traversal, then there are other considerations (one option is at the end of this email). Then there is the use of /other/ programs instead of just using bash builtin string processing; no need for perl, sed or awk (or variants) for instance And because the file names in question only ever had H in them once to start with, it wasn't necessary to match with 6H9 for the variable substitute; therefore "for filex in *H*" would have been fine for the loop. "/bin/mv -v" .... or if you trust your path and don't have aliases to interfer, you simply use "mv -v" which will give you verbose, saves doing any echoes before hand; in testing I would echo the mv command instead of doing t until I was happy with the result. Use Bash variable substitution, as in: ${variable_name/find/replace} - works fine for a single occurrence of a match If it was more occurrences, then a double slash is needed as follows: ${variable_name//find/replace} The use of the "rename" perl script is better in one way in that it doesn't clobber files, but there is also an option with mv for that as well, you can use the "i" option in order to prompt before overwriting; the "i" option will not prompt you unless there is going to be an overwrite situation. The perl script also doesn't need the for loop. Using external programs as little as possible is also more efficient, but you need at least mv or replace ... but replace works well with the perl like expression too and no for loop. So, in plain bash for your data files, it could be as simple as follows: for x in *H*;do mv -vi "${x}" "${x/H/J};done and to reverse the changes: for x in *J*;do mv -vi "${x}" "${x/J/H};done All that just uses basic BASH functionality with ONE external program, being /bin/mv in this instance; if you wanted to be anal and be more sure that you are using the proper mv command, then use /bin/mv It is entirely possible though that some "external" programs have internal bash versions as well, but I'm pretty sure that is the case for mv. If you do need to traverse directories, then something like the following might be your solution: for filex in $(find . -xdev -name '*H*') do echo mv -vi "${filex}" "${filex/H/J}" done The "-xdev" option of find keeps it in the same file system. Cheers A.