I have a directory of files whose names I want to shorten:
(3) andrew@andrew Learning_Plans $ ls -al
total 580
drwxr-xr-x 2 andrew andrew 4096 Apr 10 21:40 .
drwxr-xr-x 7 andrew andrew 4096 Apr 10 16:46 ..
-rw-rw-rw- 1 andrew andrew 17825 Mar 25 14:18 Edexcel International GCSE Physics Chapter 10 Properties of Waves Learning Plan.docx
-rw-rw-rw- 1 andrew andrew 18472 Mar 25 14:19 Edexcel International GCSE Physics Chapter 11 The Electromagnetic Spectrum Learning Plan.docx
-rw-rw-rw- 1 andrew andrew 18692 Mar 25 14:19 Edexcel International GCSE Physics Chapter 12 Light Waves Learning Plan.docx
:
etc
I ran the following from the command line:
while read x; do echo cp \'$x\' $(echo $x | cut -b38- | tr ' ' '_'); done < <(find . -type f)
which produced what I expected:
cp './Edexcel International GCSE Physics Chapter 17 Energy Resources and Electricity Generation Learning Plan.docx' Chapter_17_Energy_Resources_and_Electricity_Generation_Learning_Plan.docx
cp './Edexcel International GCSE Physics Chapter 19 Solids, Liquids and Gases Learning Plan.docx' Chapter_19_Solids,_Liquids_and_Gases_Learning_Plan.docx
cp './Edexcel International GCSE Physics Chapter 28 Cosmology Learning Plan.docx' Chapter_28_Cosmology_Learning_Plan.docx
:
etc
However, removing the echo gives:
cp: target ‘Chapter_17_Energy_Resources_and_Electricity_Generation_Learning_Plan.docx’ is not a directory
cp: target ‘Chapter_19_Solids,_Liquids_and_Gases_Learning_Plan.docx’ is not a directory
cp: target ‘Chapter_28_Cosmology_Learning_Plan.docx’ is not a directory
:
etc
I'm guessing it's something to do with spaces in the file names, but I would have thought the single-quotes would have taken care of that?
I've tried doing a copy/paste of the output of the echo back into the terminal, and it runs OK! It just won't run in the while loop.
Versions:
(3) andrew@andrew Learning_Plans $ bash --version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
(3) andrew@andrew Learning_Plans $ cat /etc/*release
DISTRIB_ID=LinuxMint
DISTRIB_RELEASE=17.3
DISTRIB_CODENAME=rosa
DISTRIB_DESCRIPTION="Linux Mint 17.3 Rosa"
NAME="Ubuntu"
VERSION="14.04, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
cp
will choke on filenames containing spaces, which is why I put the quotes in. What I'm still puzzled about is (1) whycp
in thewhile
loop seems to be ignoring the quotes, because theecho
clearly shows only two names - the source with spaces (quoted) and the target without spaces, and (2) why a direct copy/paste of thatecho
output into the command line works? – Andrew Woodward Apr 11 '19 at 11:54echo
, which is why they showed in the output. See the difference betweenprintf '%s\n' \'hello world\'
andprintf '%s\n' 'hello world'
. – Kusalananda Apr 11 '19 at 11:56echo
command outputted a correct command. That does not mean that the input toecho
was a correct command. – Kusalananda Apr 11 '19 at 12:20find
command substitution. Possibly not in this case, but in the general case. – Kusalananda Apr 11 '19 at 13:20