Swap contents of two files

13

2

This is a code-golf question. You need to take the contents of two separate files (i.txt and o.txt) and swap them. You can create a third file to help you with the process, but have your program delete it after the file contents are swapped. Renaming the files is now allowed again.

Programs must work for any file content.

Shortest code wins, all eligible submissions will be up-voted.

user10766

Posted 2013-12-28T19:29:56.007

Reputation:

2Rename the files. No need to "take the contents" and swap them to achieve the result. – Darren Stone – 2013-12-28T19:32:36.333

@Darren Stone I think that should be illegal. Thanks for catching that before answers were submitted. – None – 2013-12-28T19:33:17.160

Looks like a bad constraint, renaming is the best way to do this – hdante – 2013-12-28T20:47:18.007

1Alright, I can remove this constraint. – None – 2013-12-28T20:55:35.697

6@hdante but 'renaming files' is not exchanging their contents. On a system that uses inodes the goal here would be for i.txt's inode to contain the data from o.txt's inode, and vice versa, so that if there are hardlinks to those inodes elsewhere, their contents will appear swapped as well. Renaming can't accomplish that. – AJMansfield – 2014-05-11T03:07:19.880

Answers

9

zsh, 20

<i*>t;<o*>i*;mv t o*

Ry-

Posted 2013-12-28T19:29:56.007

Reputation: 5 283

1I like the one without a temporary file better, though: i=`<i.txt`;<o*>i*;<<<$i>o*. It’s too bad this has to be shorter. – Ry- – 2013-12-28T19:54:22.263

1Rules changed to allow renaming files. You can update your code if you wish. – None – 2013-12-28T20:56:34.077

You could save 3 chars by replacing <t>o*;rm t by mv t o* ! – F. Hauri – 2014-05-11T23:23:27.233

@F.Hauri: Ah, thanks! (There were rules against renaming at one point.) – Ry- – 2014-05-11T23:44:31.133

This code is not correct. It works only in the special case where i* and o* will match only i.txt and o.txt respectively, i.e. there is no other file with a name beginning with either "i" or "o". – Erwan Legrand – 2014-05-15T13:25:32.973

@ErwanLegrand, that’s not really a special case. Just make a new directory. Alternatively, if what Darren Stone used below is allowed (which it is, according to the asker), simply exchange for $1 and $2. – Ry- – 2014-05-16T01:11:20.157

3

Python, 77

import os;t='.txt';r,i,o,x=[os.rename,'i'+t,'o'+t,'1'+t];r(i,x);r(o,i);r(x,o)

Python, 65

import os;t='.txt'
for a,b in zip('iox','xio'):os.rename(a+t,b+t)

Python, 63

import os;t='.txt'
for a,b in 'ix','oi','xo':os.rename(a+t,b+t)

PHP, 68

<?$r=rename;$t='.txt';$r("i$t","x");$r("o$t","i$t");$r("x","o$t");?>

Windows Batch File, 42

move i.txt x&move o.txt i.txt&move x o.txt

Windows Batch File (args), 30

move %1 x&move %2 %1&move x %2

AsksAnyway

Posted 2013-12-28T19:29:56.007

Reputation: 281

I didn't know you can use $r=rename to create aliases to functions in PHP. Thanks! – A.L – 2014-05-11T15:15:32.103

2

Powershell, 44 49 bytes

$t='.txt'
ren i$t a$t -fo
ren o$t i$t
ren a$t o$t

where ren is alias for Rename-Item. The script uses and delete a third file a.txt.

mazzy

Posted 2013-12-28T19:29:56.007

Reputation: 4 832

1This can fail with certain encoding. Because gc default is UTF8NoBOM but sc default is ASCII. Try some UTF-8 files or binary files and you can see how it can fail. – AdmBorkBork – 2018-12-26T20:09:32.973

Indeed. Thanks. It need -e by -n parameters to ensure that the files unchanged. It would be nice to add a parameter -readCount 0 to performance. The script with rename is shorter :) Fixed. – mazzy – 2018-12-27T06:26:12.713

2

Two based ansers; 52 and 62 chars

shell: diff + patch (+ tee + sed...) 52

Maybe not the shorter, but I find this fun (and there is no use of temporary file):

diff -u [io]*|tee >(patch -r -)|sed 1s/i/o/|patch -R

Where content is swapped and files are modified in place:

Sample run

swapContent() { diff -u $1 $2|tee >(patch -r -)|sed 1s/$1/$2/|patch -R ;}

while read page file ;do man -Pcol\ -b $page >$file.txt;done <<<$'man i\nbash o'
printf "%s %8d  %s\n" $(join -j 2 <(stat -c '%s %n' [io]*) <(md5sum [io]*))
swapContent [io]*
printf "%s %8d  %s\n" $(join -j 2 <(stat -c '%s %n' [io]*) <(md5sum [io]*))

Could produce something like:

i.txt    46007  1da1f7533e0eab1e97cce97bb7ca1d3b
o.txt   321071  7dcd230890faf4ef848d4745eda14407
patching file o.txt
i.txt   321071  7dcd230890faf4ef848d4745eda14407
o.txt    46007  1da1f7533e0eab1e97cce97bb7ca1d3b

use of xargs to simplify mv requests

Not as funny, but nice anyway.

set -- {i,o}.txt t&&eval 'xargs -n2 mv<<<"' \${1,3,2,1,3,2} \"

F. Hauri

Posted 2013-12-28T19:29:56.007

Reputation: 2 654

Nota: As first patch output is not redirected, they become garbage on second patch command. This is the reason because only one patching file o.txt appear. – F. Hauri – 2014-05-11T22:20:55.067

2

PHP, 89

I thought I'd give it a shot.

<?php $f1='f1.txt';$f2='f2.txt';$ft='ft.txt';copy($f1,$ft);copy($f2,$f1);rename($ft,$f2);

Ungolfed version:

<?php
$f1 = 'f1.txt';
$f2 = 'f2.txt';
$ft = 'ft.txt';

copy($f1, $ft);
copy($f2, $f1);
rename($ft, $f2);

Apparently I took 2 answers of here and combined them.. oh well.

MisterBla

Posted 2013-12-28T19:29:56.007

Reputation: 181

2

Ruby, 72 bytes

Wow! A Ruby code golf! I don't think that's ever been attempted before!

In all reality though, this required some nice Ruby shortcuts and a couple patterns which I found. It was my first golf ever and it was very fun to do. Without further ado, here's the golfed code:

3.times{|x|x*=2;t=".txt";a=([?i,?a,?o]*2);File.rename(a[x]+t,a[x+1]+t)}

And the ungolfed version

3.times do |x|
    x = x * 2
    t=".txt"
    a=([?i,?a,?o]*2)
    File.rename(a[x]+t, a[x+1]+t)}
end

The key factor in this is that the parameters passed to the File.rename are this, exactly:

File.rename "i.txt", "a.txt"
File.rename "o.txt", "i.txt"
File.rename "a.txt", "o.txt"

Hope this (doesn't) make sense!

Aearnus

Posted 2013-12-28T19:29:56.007

Reputation: 251

1

Windows Batch, 39 bytes

ren i.txt x&ren o.txt i.txt&ren x o.txt

peter ferrie

Posted 2013-12-28T19:29:56.007

Reputation: 804

1

Ruby

i1="i.txt"
i2="o.txt"
c1=IO.readlines(i2)
c2=IO.readlines(i1)
File.open(i1){|x|x.puts(c1)}
File.open(i2){|x|x.puts(c2)}

Shortened version:

a=["i.txt","o.txt"]
(0..1).each{|x|b[x]=IO.readlines(a[x])*"\n"}
a.reverse!
(0..1).each{|x|IO.write(a[x],b[x])}

Not the shortest, but very simple and easy to read. Also, no intermediate files, only RAM.

user11485

Posted 2013-12-28T19:29:56.007

Reputation:

1Given that it’s a [tag:code-golf], you could at least take out the spaces and try somewhat for the shortest. – Ry- – 2013-12-28T20:42:44.763

Totally didn't realize it was code-golf, sorry – None – 2013-12-28T21:15:21.710

1

PHP

$f1 = 'file1.txt';
$f2 = 'file2.txt';

$f1contents = file_get_contents ($f1);
$f2contents = file_get_contents ($f2);

file_put_contents($f1, $f2contents);
file_put_contents($f2, $f1contents);

Eisa Adil

Posted 2013-12-28T19:29:56.007

Reputation: 135

10Thats not really golfy :( – Jakob Bowyer – 2013-12-30T11:45:26.263

1

Shell script, 24

Works in Bash and probably most shells. Pass with your two filenames as parameters.

mv $1 ੴ;mv $2 $1;mv ੴ $2

If you want fixed filenames then this will do it, for a 12 char penalty:

mv i.txt ੴ;mv o.txt i.txt;mv ੴ o.txt

Darren Stone

Posted 2013-12-28T19:29:56.007

Reputation: 5 072

@minitech, yes it does. 'ੴ' becomes 'o.txt'. Those are mv operations, not cp. – Darren Stone – 2013-12-29T01:44:01.463

Second best answer so far! Reduce it by two characters and you win! I do not care about fixed filenames. – None – 2013-12-29T04:28:21.717

1

Python:

import os
l,e='i_o'*2,'.txt'
for x,y in zip(l,l[1:])[::2]:
 os.rename(x+e,y+e)

tamasgal

Posted 2013-12-28T19:29:56.007

Reputation: 111

1

Tcl, 122 bytes

set A [read [open i.txt]]
puts [set i [open i.txt w]] [read [open o.txt]]
puts [set o [open o.txt w]] $A
close $i
close $o

Try it online!


Tcl, 169 bytes

set A [read [set i [open i.txt r]]]
set B [read [set o [open o.txt r]]]
close $i
close $o
puts [set i [open i.txt w]] $B
puts [set o [open o.txt w]] $A
close $i
close $o

Try it online!

sergiol

Posted 2013-12-28T19:29:56.007

Reputation: 3 055

1

Lua, 71 70 bytes

_ENV=os t='.txt'i,o,r='i'..t,'o'..t,rename r(i,t)r(o,i)r(t,o)remove(t)

Try it online!

Define os, the operating system library, as the global table so we can write rename and remove instead of os.rename and os.remove. (Incidentally this also means the one-letter variables are actually fields in the os table.) Make short alias for os.rename to save some space. Set up filename variables, using '.txt' as temporary file. Do the renaming and deleting.

cyclaminist

Posted 2013-12-28T19:29:56.007

Reputation: 191

1

PHP, 52 bytes

AsksAnyway´s php modernized & golfed:

($r=rename)(i.$e=".txt",x);$r(o.$e,i.$e);$r(x,o.$e);

Run with php -nr '<code>'.

Titus

Posted 2013-12-28T19:29:56.007

Reputation: 13 814

1

Windows Batch File (48)

type i.txt>a&type o.txt>i.txt&type a>o.txt&del a

I forgot about the move command when I wrote this...

kitcar2000

Posted 2013-12-28T19:29:56.007

Reputation: 2 689

You just overwrote my a file! – Danny – 2014-05-14T16:12:46.620

@Danny The question states that you may create another file, but it must be deleted. – kitcar2000 – 2014-05-14T16:21:20.810

1

C 162

Golfed: uses t.txt as tmp file and swaps names then removes t.txt.

#include <stdio.h>
#define R(x,y) rename(x,y)
#define X(x) remove(x)
int main(){char *i="i.txt",*o="o.txt",*t="t.txt";R(i,t);X(i);R(o,i);R(t,o);X(t);return 0;}

Edit: removed 2 spaces

bacchusbeale

Posted 2013-12-28T19:29:56.007

Reputation: 1 235

1

PHP - 172

Golfed version of @EisaAdil's answer

$f1='file1.txt';$f2='file2.txt';$f1contents=file_get_contents($f1);$f2contents=file_get_contents($f2);file_put_contents($f1,$f2contents);file_put_contents($f2,$f1contents);

Spedwards

Posted 2013-12-28T19:29:56.007

Reputation: 159

1

PHP, 45

<?php
copy('i','t');copy('o','i');rename('t','o');

Not very golfy but shortest PHP so far.

mleko

Posted 2013-12-28T19:29:56.007

Reputation: 290

file extensions are missing. – Titus – 2018-12-26T09:05:30.613

1

Rebol - 46 (rename file) or 55 (r/w contents)

Rename file (using t as temporary file):

r: :rename 
r i: %i.txt %t
r o: %o.txt i
r %t o

Read in then write out file contents:

a: read i: %i.txt
b: read o: %o.txt
write o a 
write i b

draegtun

Posted 2013-12-28T19:29:56.007

Reputation: 1 592

1

Groovy - 99 chars

This is my attempt, with Groovy 2.2.1. I tried to do it without renaming:

f={new File(it+".txt")}
w={x,y->x.withWriter{it.write y}}
i=f "i"
o=f "o"
t=i.text
w i,o.text
w o,t

Ungolfed:

file = { new File(it+".txt") }
writeTextToFile = { x,y -> x.withWriter{it.write y} }

iFile = file("i")
oFile = file("o")

iText = iFile.text
writeTextToFile (iFile,oFile.text)
writeTextToFile (oFile,iText)

Michael Easter

Posted 2013-12-28T19:29:56.007

Reputation: 585

1

VBA (148...132) and (126...110)

Renaming with a temp file t in the c:\ drive. Also first attempt at golf :S

Sub s():Set f=CreateObject("Scripting.FileSystemObject"):i="c:\i.txt":t="c:\t":f.MoveFile i,t:f.MoveFile "c:\o.txt",i:Kill t:End Sub

If scrrun.dll is referenced already, could cut it down a bit to 126...110.

Sub s():Set f=new FileSystemObject:i="c:\i.txt":t="c:\t":f.MoveFile i,t:f.MoveFile "c:\o.txt",i:Kill t:End Sub

jaybee3

Posted 2013-12-28T19:29:56.007

Reputation: 11

Looks like your code has a lot of whitespace. Are you sure they are needed? You can have a much better score if you remove them. – user12205 – 2014-05-15T10:27:17.957

I don't think it's needed the editor just threw it in. Removed apart from where it's necessary :) – jaybee3 – 2014-05-15T12:32:29.167

1

C: 65 characters

#define r(a,b)rename(#a".txt",#b".txt");
main(){r(i,)r(o,i)r(,o)}

A quite simple solution in C that does the job. It uses a temporary name (.txt) for one of the files before giving it its proper new name.

Ungolfed (note how the syntax highlighting fails in the define, a bug has been uncovered!):

#include <stdio.h>

#define r(a, b) rename(#a ".txt", #b ".txt");

int main()
{
    r(i,  ) // rename("i.txt",  ".txt");
    r(o, i) // rename("o.txt", "i.txt");
    r( , o) // rename( ".txt", "o.txt");

    return 0;
}

Fors

Posted 2013-12-28T19:29:56.007

Reputation: 3 020

1

Perl, 120 bytes (Contents swapping without file renaming)

use open IO,':bytes';undef$/;open I,"<i.txt";$I=<I>;open I,"<o.txt";open O,">i.txt";print O<I>;open O,">o.txt";print O$I

The file contents is put into memory and written back to the other file. Thus i.txt and o.txt must fit into memory.

Since the file contents are actually exchanged, hard links are updated automatically, see AJManfield's comment.

Ungolfed:

use open IO => ':bytes'; # binmode, not needed for Unix, but needed for Windows
undef $/;                # read whole file instead of lines
open I, "<i.txt";        # open i.txt for reading
$I = <I>;                # read i.txt
open I, "<o.txt";        # open o.txt for reading
open O, ">i.txt";        # open i.txt for writing
print O <I>;             # read o.txt and put the contents in i.txt
open O, ">o.txt";        # open o.txt for writing
print O $I;              # write o.txt with contents of old i.txt

Heiko Oberdiek

Posted 2013-12-28T19:29:56.007

Reputation: 3 841

0

SmileBASIC, 36 35 bytes

@L
RENAME@OI[2-I],@IO[I]I=I+1GOTO@L

12Me21

Posted 2013-12-28T19:29:56.007

Reputation: 6 110