Reputation: 63
I want to cut a certain length of string from the start of my file and append it to my filename. Is there a one-liner that can do this for a whole directory of files?
For example, I have the file 1.txt, with the following contents:
123456abcdefg12345678...
I want to rename the file to 1_123456.txt, and edit the contents to:
abcdefg12345678....
I have created a bash script to solve this problem, like so:
for f in ./*; do
a = $(head -c 8 $f)
cut -c 9- > $f
mv {,$a_}$f
done
But this doesn't do what it's supposed to do- the problem seems to be in the mv line. I would also appreciate it if a one-liner could also do the trick.
Upvotes: 0
Views: 1419
Reputation: 212268
$ echo 123456abcdefg12345678 > 1.txt
$ tail -c +7 1.txt > 1_$(head -c +6 1.txt).txt ; rm 1.txt .
$ cat 1_123456.txt
abcdefg12345678
Upvotes: 1
Reputation: 1774
Maybe not a one liner (unless you put it into a shell script) but you could try this:
#!/bin/bash
# require two parameters:
# 1 the name of the input directory and
# 2 the name of the output directory
if [ $# -ne 2 ]
then
echo usage
exit 1
fi
INDIR=$1
OUTDIR=$2
CHAR_CNT=4 # Number of chars to take from file content and insert into output file name
# Create the output directory just in case it does not exist.
mkdir -p $OUTDIR
# for each file.
for FILENAME in $INDIR/*
do
if [ -f $FILENAME ] # Make sure it is a regular file.
then
BASENAME=`basename $FILENAME` # Extract just the file name.
NAMEPART=${BASENAME%.*} # From the file name, get just the name part.
EXT=${BASENAME##*.} # From the file name, get just the extension.
PREFIX=`head -1 $FILENAME | cut -c 1-$CHAR_CNT` # Get the first n characters from the input file.
NEWFILE=$OUTDIR/${NAMEPART}_$PREFIX.$EXT # Construct the output file name (and output path)
# Degugging statements to show what is going on.
#echo file: $FILENAME - NamePart: $NAMEPART, extension: $EXT, prefix = $PREFIX
#echo new file name: $NEWFILE
# Transfer the input file to the output, remove the first n characters from the file.
# The output file will be named as per the format originalName_charsFromFile.extension
sed "1s/^.\{$CHAR_CNT\}//" < $FILENAME > $NEWFILE
echo "processed: $FILENAME -> $NEWFILE"
else # Not a regular file.
echo skipping $FILENAME
fi
done
I put the above into a script called renameSpecial.sh
. When I run it, I get the result shown below.
gmc@linux-ihon:~/projects/so/renFil> #### Starting point - input files
gmc@linux-ihon:~/projects/so/renFil> tree .
.
└── sampleData
├── file1.txt
├── file2.txt
├── testdir
│ └── ignoredFile.txt
├── t.txt
└── x.y.z.txt
2 directories, 5 files
gmc@linux-ihon:~/projects/so/renFil> cat sampleData/x.y.z.txt
1234567890abcdefg
gmc@linux-ihon:~/projects/so/renFil> cat sampleData/t.txt
12aaaa
34bbb
56cccc
gmc@linux-ihon:~/projects/so/renFil> cat sampleData/file2.txt
abcdefg
gmc@linux-ihon:~/projects/so/renFil> cat sampleData/file1.txt
aaaaaaa
gmc@linux-ihon:~/projects/so/renFil>
gmc@linux-ihon:~/projects/so/renFil>
gmc@linux-ihon:~/projects/so/renFil> #### Run the command
gmc@linux-ihon:~/projects/so/renFil> renameSpecial.sh
usage: /home/glennm/bin/renameSpecial.sh inDir outDir
where:
inDir the name of a directory containing the input files
outDir the name of a directory that will contain the output files
if outDir does not exist, this script will create it.
gmc@linux-ihon:~/projects/so/renFil>
gmc@linux-ihon:~/projects/so/renFil> renameSpecial.sh sampleData outData
processed: sampleData/file1.txt -> outData/file1_aaaa.txt
processed: sampleData/file2.txt -> outData/file2_abcd.txt
skipping sampleData/testdir
processed: sampleData/t.txt -> outData/t_12aa.txt
processed: sampleData/x.y.z.txt -> outData/x.y.z_1234.txt
gmc@linux-ihon:~/projects/so/renFil>
gmc@linux-ihon:~/projects/so/renFil> #### Result new directory with *new* file names
gmc@linux-ihon:~/projects/so/renFil>
gmc@linux-ihon:~/projects/so/renFil> tree .
.
├── outData
│ ├── file1_aaaa.txt
│ ├── file2_abcd.txt
│ ├── t_12aa.txt
│ └── x.y.z_1234.txt
└── sampleData
├── file1.txt
├── file2.txt
├── testdir
│ └── ignoredFile.txt
├── t.txt
└── x.y.z.txt
3 directories, 9 files
gmc@linux-ihon:~/projects/so/renFil>
gmc@linux-ihon:~/projects/so/renFil> ### Finally, the chars used in the file names are removed from the beginning of the file.
gmc@linux-ihon:~/projects/so/renFil>
gmc@linux-ihon:~/projects/so/renFil> cat outData/x.y.z_1234.txt
567890abcdefg
gmc@linux-ihon:~/projects/so/renFil> cat outData/t_12aa.txt
aa
34bbb
56cccc
gmc@linux-ihon:~/projects/so/renFil>
If you want to "rename" the files, then simply add an rm $FILENAME
after the sed
step near the bottom of the if statement.
You say that you want to rename the files, my example creates a new version of the processed files in a new location. This could still meet your needs, just rename your input directory before you start, or copy the output files back to the input directory (e.g. as a final step). I just did it this way as it aids debugging, I can run it as many times as I like without having to recreate my inputs and so on.
Upvotes: 0